Class DefaultSubscriptionPricingService

java.lang.Object
com.broadleafcommerce.subscriptionoperation.service.DefaultSubscriptionPricingService
All Implemented Interfaces:
SubscriptionPricingService

public class DefaultSubscriptionPricingService extends Object implements SubscriptionPricingService
  • Constructor Details

  • Method Details

    • priceSubscriptions

      public List<SubscriptionPriceResponse> priceSubscriptions(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.Cart cart, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: SubscriptionPricingService
      Prices the cart's subscription items, returning SubscriptionPriceResponses describing how much the customer should be charged now, & estimations for how much & when they'll be charged in the future as part of subscription billing.
      Specified by:
      priceSubscriptions in interface SubscriptionPricingService
      Parameters:
      cart - The cart that we are pricing.
      contextInfo - Context information around sandbox and multitenant state.
      Returns:
      a list of SubscriptionPriceResponses
    • bulkUpdateSubscriptionPricing

      public Set<String> bulkUpdateSubscriptionPricing(@NonNull @NonNull BulkPriceUpdateSubscriptionRequest request, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: SubscriptionPricingService
      Adds a price data change for all qualifying subscriptions.
      Specified by:
      bulkUpdateSubscriptionPricing in interface SubscriptionPricingService
      Parameters:
      request - The request containing the price data ID and the scope of the price change
      contextInfo - Additional sandbox and multitenant info
      Returns:
      The subscription IDs that were updated
    • shouldProcessPriceChangeImmediately

      protected boolean shouldProcessPriceChangeImmediately(@NonNull @NonNull PriceDataChange priceDataChange)
      Hook point to decide whether a PriceDataChange should be applied immediately to the related Subscriptions and possibly existing BillingEvents.

      For example, a change with PriceDataChange.getPriceChangeEffectiveType() of DefaultPriceChangeEffectiveType.NEXT_BILL_DATE should lead to an immediate update of the subscription's price data, setting up the subscription billing job to generate BillingEvents based on the new prices on the Subscription.getNextBillDate().

      Parameters:
      priceDataChange - The PriceDataChange that is to be applied to various subscriptions
      Returns:
      whether a PriceDataChange should be applied immediately to the related Subscriptions and possibly existing BillingEvents.
    • getSubscriptionWithItemsByCartItemMap

      protected <C extends com.broadleafcommerce.cart.client.domain.CartItem> Map<C,SubscriptionWithItems> getSubscriptionWithItemsByCartItemMap(@NonNull @NonNull List<C> rootItems, @NonNull @NonNull Map<String,C> cartItemBySubscriptionId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Builds a Map of <CartItem, SubscriptionWithItems> from the rootItems and cartItemBySubscriptionId for quick lookup of subscription by its cartItem.
      Parameters:
      rootItems - a collection of the subscriptionRootItem
      cartItemBySubscriptionId - a Map of <CartItem, SubscriptionWithItems>
      contextInfo - additional sandbox and multitenant info
      Returns:
      a Map of <CartItem, SubscriptionWithItems>
    • buildCartItemBySubscriptionIdMap

      protected <C extends com.broadleafcommerce.cart.client.domain.CartItem> Map<String,C> buildCartItemBySubscriptionIdMap(@NonNull @NonNull List<C> rootItems)
      Builds a Map of <String, CartItem> from the rootItems for quick lookup of cartItem by its subscriptionId.
      Parameters:
      rootItems - a collection of the subscriptionRootItem
      Returns:
      a Map of <String, CartItem>
    • processPricingWorkflows

      protected void processPricingWorkflows(BulkPriceUpdateSubscriptionRequest request, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, Set<SubscriptionOwnerInfo> needsPriceChange, Set<String> updated)
      Launch a price change workflow for each subscription updated with a price change record.
      Parameters:
      request - The request containing the price data ID and the scope of the price change
      contextInfo - Additional sandbox and multitenant info
      needsPriceChange - Subscription related information for pricing
      updated - The subscription IDs that were updated
    • filterSubscriptionOwnerInfosBySegments

      protected Set<SubscriptionOwnerInfo> filterSubscriptionOwnerInfosBySegments(BulkPriceUpdateSubscriptionRequest request, List<SubscriptionOwnerInfo> subscriptionOwnerInfos, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Filters the SubscriptionOwnerInfo in the given Page by the segments in the given BulkPriceUpdateSubscriptionRequest.
      Parameters:
      request - The BulkPriceUpdateSubscriptionRequest containing the segments to filter by
      subscriptionOwnerInfos - The SubscriptionOwnerInfo instances to filter
      contextInfo - Additional sandbox and multitenant info
      Returns:
      The relevant SubscriptionOwnerInfo instances
    • hydrateCancellationPoliciesForCartItems

      protected <T extends com.broadleafcommerce.cart.client.domain.CartItem> void hydrateCancellationPoliciesForCartItems(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.Cart cart, @NonNull @NonNull Collection<T> rootItems, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Retrieves all of the CancellationPolicies for the root subscription items for a cancellation flow and hydrates them onto the CartItem in their CartItem.getInternalAttributes() as CartItemAttributeConstants.Internal.HYDRATED_CANCELLATION_POLICY.
      Type Parameters:
      T - The type of CartItem
      Parameters:
      cart - The cart that we are pricing.
      rootItems - The root subscription items being acted on
      contextInfo - Context information around sandbox and multitenant state.
      Throws:
      IllegalSubscriptionPricingStateException - If a Cancellation Policy is not found an item or if it indicates that cancellation is not allowed for an item.
    • readAllCancellationPolicies

      protected <T extends com.broadleafcommerce.cart.client.domain.CartItem> Map<String,CancellationPolicy> readAllCancellationPolicies(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.Cart cart, @NonNull @NonNull Collection<T> rootItems, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Reads all CancellationPolicies for the given CartItems representing root SubscriptionItems in a cancellation flow (DefaultSubscriptionActionFlow.CANCEL or DefaultSubscriptionActionFlow.TERMINATE).
      Type Parameters:
      T - The type of CartItem
      Parameters:
      cart - The cart that we are pricing.
      rootItems - The CartItems representing root SubscriptionItems
      contextInfo - Additional sandbox and multitenant info
      Returns:
      All CancellationPolicies for the given CartItems
    • identifySubscriptionRootItemsAsStream

      protected Stream<com.broadleafcommerce.cart.client.domain.CartItem> identifySubscriptionRootItemsAsStream(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.Cart cart, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • identifySubscriptionRootItems

      protected List<com.broadleafcommerce.cart.client.domain.CartItem> identifySubscriptionRootItems(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.Cart cart, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines which CartItems on the Cart are root SubscriptionItems.
      Parameters:
      cart - A Cart to be priced
      contextInfo - Additional sandbox and multitenant info
      Returns:
      The CartItems on the Cart are root SubscriptionItems.
    • isSubscriptionItem

      protected boolean isSubscriptionItem(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem)
    • isSeparateFromPrimaryItem

      protected boolean isSeparateFromPrimaryItem(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem)
    • getSubscriptionActionFlow

      protected String getSubscriptionActionFlow(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.Cart cart, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • priceSubscription

      protected SubscriptionPriceResponse priceSubscription(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • populatePeriodInfoOnPriceResponse

      protected SubscriptionPriceResponse populatePeriodInfoOnPriceResponse(@NonNull @NonNull SubscriptionPriceResponse response, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Populates SubscriptionPriceResponse.getPeriodType() and SubscriptionPriceResponse.getPeriodFrequency(). The source of these values can vary depending on the flow.
      Parameters:
      response - The SubscriptionPriceResponse to populate
      pricingContext - The SubscriptionPricingContext containing the info to use
      contextInfo - Additional sandbox and multitenant info
      See Also:
    • buildSubscriptionPricingContext

      protected SubscriptionPricingContext buildSubscriptionPricingContext(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.Cart cart, @NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem subscriptionRootItem, @Nullable SubscriptionWithItems maybeSubscriptionWithItems, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Builds out a SubscriptionPricingContext containing all the important contextual information needed to price subscriptions in a Cart.
      Parameters:
      cart - The Cart containing items that represent subscriptions.
      subscriptionRootItem - The current CartItem representing the root item of a subscription being priced.
      contextInfo - Additional sandbox and multitenant info
      Returns:
      A SubscriptionPricingContext containing all the important contextual information needed to price subscriptions in a Cart.
    • buildBasicSubscriptionPricingContext

      protected SubscriptionPricingContext buildBasicSubscriptionPricingContext(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.Cart cart, @NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem subscriptionRootItem, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • hasFreeTrial

      protected boolean hasFreeTrial(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem)
    • getExistingSubscriptions

      protected <C extends com.broadleafcommerce.cart.client.domain.CartItem> List<SubscriptionWithItems> getExistingSubscriptions(@NonNull @NonNull List<C> subscriptionRootItems, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • getExistingSubscriptionItemId

      @Nullable protected String getExistingSubscriptionItemId(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • populatePricingContextFromExistingSubscription

      protected void populatePricingContextFromExistingSubscription(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionWithItems existingSubscriptionWithItems, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • hasBillingFrequencyChange

      protected boolean hasBillingFrequencyChange(@NonNull @NonNull Subscription existingSubscription, @NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem subscriptionRootItem)
      Determines if the billing frequency has changed between the existing subscription and the subscription root item.

      Note that the subscription root item does not have a RecurringPriceDetail in a cancellation flow.

      Parameters:
      existingSubscription - the existing Subscription
      subscriptionRootItem - the current CartItem representing the root item of a subscription
      Returns:
      true if the billing frequency has changed, false otherwise
    • populateTermDetailsForExistingSubscription

      protected void populateTermDetailsForExistingSubscription(@NonNull @NonNull Subscription existingSubscription, @NonNull @NonNull List<RemovedAdjustment> removedAdjustments, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Populates the term details for an existing Subscription based on the RemovedAdjustments.

      If the free trial is lost, the term dates are re-calculated based on the action date.

      Parameters:
      existingSubscription - the existing Subscription
      pricingContext - the current SubscriptionPricingContext
      removedAdjustments - the list of RemovedAdjustments needed to determine whether the free trial is lost
      contextInfo - context surrounding the multi-tenant state
    • populatePricingContextFromCancellationPolicy

      protected void populatePricingContextFromCancellationPolicy(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.Cart cart, @NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem subscriptionRootItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Parameters:
      cart - The Cart containing items that represent subscriptions.
      subscriptionRootItem - The current CartItem representing the root item of a subscription being priced.
      pricingContext - The SubscriptionPricingContext being populated.
      contextInfo - Additional sandbox and multitenant info
      See Also:
    • identifyRemovedSubscriptionItems

      protected List<SubscriptionItem> identifyRemovedSubscriptionItems(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionWithItems existingSubscriptionWithItems, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • populatePricingContextFromCartItem

      protected void populatePricingContextFromCartItem(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Populates contextual pricing information when there is no existing Subscription, e.g., when this is a create flow.
      Parameters:
      pricingContext - The SubscriptionPricingContext to populate
      contextInfo - Additional sandbox and multitenant info
    • getSubscriptionPaymentStrategy

      protected String getSubscriptionPaymentStrategy(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem subscriptionRootItem, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineStartOfTermsDate

      protected Instant determineStartOfTermsDate(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem rootItem, @NonNull @NonNull String termDurationType, @NonNull @NonNull Integer termDurationLength, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineNextBillDateForNewSubscription

      protected Instant determineNextBillDateForNewSubscription(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the next bill date for a newly signed up subscription, which is the subscription action date / signup date + 1 period.

      Regardless of the payment strategy, the next bill date is the same. Since for DefaultSubscriptionPaymentStrategy.PREPAID, the period from signup date till signup date + 1 period is the DUE NOW period, so it's next bill date is also the signup date + 1 period, the same as DefaultSubscriptionPaymentStrategy.POSTPAID (POSTPAID doesn't have a DUE NOW period).

      If there is a free trial, then the date is delayed by the duration of the free trial.

      Parameters:
      pricingContext - The SubscriptionPricingContext containing the necessary details
      contextInfo - context surrounding the multi-tenant state
      Returns:
      the next bill date for a new subscription.
    • determineNextBillDateForExistingSubscription

      protected Instant determineNextBillDateForExistingSubscription(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the next bill date for an existing subscription, which is unchanged from the SubscriptionPricingContext.getExistingSubscription()'s Subscription.getNextBillDate(). But if the free trial is lost due to the modification, then the action date becomes the next bill date.
      Parameters:
      pricingContext - The SubscriptionPricingContext containing the necessary details
      contextInfo - context surrounding the multi-tenant state
      Returns:
      the next bill date for the existing subscription.
    • buildPeriodDefinitions

      protected Map<Integer,PeriodDefinition> buildPeriodDefinitions(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • buildDueNowPeriodDefinition

      @Nullable protected PeriodDefinition buildDueNowPeriodDefinition(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Builds the period definition for the DUE NOW period.

      For create flows, this covers the period between signup date and the next bill date.

      For non-create flows, the period definition is built based on the existing Subscription.getCurrentPeriodDefinition(), unless free trial is lost.

      Parameters:
      pricingContext - the current SubscriptionPricingContext
      contextInfo - context surrounding the multi-tenant state
      Returns:
      the period definition for the DUE NOW period
    • buildFirstFuturePeriodDefinition

      protected PeriodDefinition buildFirstFuturePeriodDefinition(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Builds the 1st future period definition, which is the period after DUE NOW.
      Parameters:
      pricingContext - the current SubscriptionPricingContext
      contextInfo - context surrounding the multi-tenant state
      Returns:
      the 1st future period definition, which is the period after DUE NOW.
    • getEstimatedFuturePaymentCount

      protected long getEstimatedFuturePaymentCount(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the number of future billing periods to estimate. This will use either SubscriptionPricingContext.getNumberOfPeriodsLeftInTerm(), or, if that's null, then it will default to the next 12 periods.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      contextInfo - Additional sandbox and multitenant info
      Returns:
      The number of future billing periods to estimate
    • determinePeriodStartDate

      protected Instant determinePeriodStartDate(@NonNull @NonNull Instant previousBillDate, @NonNull @NonNull Instant billDate, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • populatePeriodEndDate

      protected PeriodDefinition populatePeriodEndDate(@NonNull @NonNull PeriodDefinition periodDefinition, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determinePeriodEndDate

      protected Instant determinePeriodEndDate(@NonNull @NonNull PeriodDefinition periodDefinition, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • populateDueNowDetails

      protected SubscriptionPriceResponse populateDueNowDetails(@NonNull @NonNull SubscriptionPriceResponse response, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • buildDueNowItemDetails

      protected <T extends SubscriptionItemPriceDetail> List<T> buildDueNowItemDetails(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • buildItemDetails

      protected <T extends SubscriptionItemPriceDetail> List<T> buildItemDetails(@Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • buildItemDetailForCartItem

      protected <T extends SubscriptionItemPriceDetail> T buildItemDetailForCartItem(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @Nullable com.broadleafcommerce.cart.client.domain.CartItem parentCartItem, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • populateAdjustmentPriceDetails

      protected void populateAdjustmentPriceDetails(@NonNull @NonNull SubscriptionItemPriceDetail itemPriceDetail, @Nullable com.broadleafcommerce.cart.client.domain.CartItem cartItem, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Populates the SubscriptionItemPriceDetail.getAdjustmentPriceDetailsByAdjustmentRef() based on the current item adjustments from CartItem.getItemAdjustments() and the existing subscription item adjustments from SubscriptionItem.getSubscriptionItemAdjustments().

      Note that SubscriptionItemAdjustmentPriceDetail.getProratedUnitDiscountAmount() is only relevant for currently applied adjustments (CartItem.getItemAdjustments()), while SubscriptionItemAdjustmentPriceDetail.getCreditedUnitDiscountAmount() and SubscriptionItemAdjustmentPriceDetail.getPriorUnbilledUnitDiscountAmount() are only relevant for existing subscription item adjustments (SubscriptionItem.getSubscriptionItemAdjustments()).

      This is because the credited amount is from the amount the user may have already paid for and prior unbilled amount is from the amount the user may have already consumed but not yet paid for, both of which requires the existing subscription item adjustments prior to the subscription modification be incorporated into the calculations.

      Parameters:
      itemPriceDetail - the SubscriptionItemPriceDetail to populate the adjustment details for
      cartItem - the current CartItem to get the adjustments from. This is nullable when the adjustment price details are being populated for a removed subscription item
      existingSubscriptionItemId - the existing SubscriptionItem.getId() to get the adjustments from. This is only relevant for discounts for credited and prior unbilled amounts. This is nullable when the current CartItem is net-new and not for modifying an existing SubscriptionItem
      period - the period to populate the adjustment details for
      pricingContext - the current SubscriptionPricingContext
      contextInfo - context surrounding the multi-tenant state
    • buildItemAdjustmentPriceDetail

      protected SubscriptionItemAdjustmentPriceDetail buildItemAdjustmentPriceDetail(@NonNull @NonNull String adjustmentRef, @Nullable String subscriptionItemAdjustmentRef, @Nullable Integer existingItemAdjustmentQuantity, @Nullable Integer currentItemAdjustmentQuantity, @NonNull @NonNull SubscriptionPricingContext pricingContext)
    • hasMatchingBillingFrequency

      protected boolean hasMatchingBillingFrequency(@NonNull @NonNull com.broadleafcommerce.order.common.domain.RecurringPriceDetail recurringPriceDetail, @NonNull @NonNull SubscriptionPricingContext pricingContext)
    • shouldOverrideDueNowItemQuantity

      protected boolean shouldOverrideDueNowItemQuantity(@Nullable Integer existingItemQuantity, Integer newItemQuantity, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines if using the existing item's quantity should be used for due now price calculations. Specifically, this should return true when the customer decreases the quantity of a prepaid item. In this case, instead of immediately revoking access to that item in the period, we'll maintain access until the end of the period. Because of this, the pricing result should mimic the item quantity being retained.
      Parameters:
      existingItemQuantity - The existing SubscriptionItem's quantity.
      newItemQuantity - The new SubscriptionItem's quantity.
      period - The period which is being considered for the quantity override
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      contextInfo - context surrounding the multi-tenant state
      Returns:
      whether the item's existing quantity should be used for due now pricing concerns
    • buildItemDetailsForDependentCartItems

      protected <T extends SubscriptionItemPriceDetail> List<T> buildItemDetailsForDependentCartItems(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • populateProratedAmounts

      protected void populateProratedAmounts(SubscriptionItemPriceDetail itemDetail, @NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • populateProratedAmounts

      protected void populateProratedAmounts(SubscriptionItemPriceDetail itemDetail, @NonNull @NonNull SubscriptionItem removedSubscriptionItem, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • populateProratedAmounts

      protected void populateProratedAmounts(SubscriptionItemPriceDetail itemDetail, @NonNull @NonNull javax.money.MonetaryAmount amountToProrate, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • populateCancellationCharges

      protected void populateCancellationCharges(@NonNull @NonNull SubscriptionItemPriceDetail itemDetail, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Populates the charges related to the cancellation of the subscription.

      This is only relevant for DefaultCancellationStrategy.IMMEDIATE cancellations that are charging for the remainder of terms.

      "Remainder of terms" is considered to be anything after the DefaultSubscriptionActionFlow.CANCEL action, so this is the sum of the charges for the remainder of the terms' future periods and the prorated charge for the current period during the cancellation.

      Parameters:
      itemDetail - the SubscriptionItemPriceDetail to populate the cancellation charges
      existingSubscriptionItemId - the existing SubscriptionItem.getId() that is cancelled
      period - the period to populate the cancellation charges for
      pricingContext - the current SubscriptionPricingContext
      contextInfo - context surrounding the multi-tenant state
    • determineProratedUnitAmount

      protected javax.money.MonetaryAmount determineProratedUnitAmount(@Nullable com.broadleafcommerce.cart.client.domain.CartItem parentCartItem, @NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      For a SubscriptionItemPriceDetail, determines the amount owed for the rest of the billing period based on how much of the billing period has elapsed at the time of the subscription action.

      For example, if a normal bill is due on the first of each month and the user modifies a subscription in the middle of the month (say the 15th), then the prorated amount is the amount due for the remaining 15 days of the month: The total monthly amount due, divided by the number of days in the month, times 15 (the days left).

      Parameters:
      parentCartItem - the parent cart item for the specified cart item. Usually, this is the item that has the dependent cart items. Will be null if the cart item is the root.
      cartItem - the child item whose price we're wanting to identify.
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      contextInfo - context surrounding the multi-tenant state
      Returns:
      The amount owed for the rest of the billing period based on how much of the billing period has elapsed at the time of the subscription action
      See Also:
    • determineProratedUnitDiscountAmount

      protected javax.money.MonetaryAmount determineProratedUnitDiscountAmount(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @NonNull com.broadleafcommerce.order.common.domain.Adjustment adjustment, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineProratedUnitDiscountAmountForCreateFlow

      protected javax.money.MonetaryAmount determineProratedUnitDiscountAmountForCreateFlow(@NonNull com.broadleafcommerce.order.common.domain.Adjustment adjustment, @NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineProratedUnitDiscountAmountForModificationFlow

      protected javax.money.MonetaryAmount determineProratedUnitDiscountAmountForModificationFlow(@NonNull com.broadleafcommerce.order.common.domain.Adjustment adjustment, @NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • isFirstPeriod

      protected boolean isFirstPeriod(@Nullable Integer periodNumber, @NonNull @NonNull SubscriptionPricingContext pricingContext)
      Determines whether the given period is the first period based on the given SubscriptionPricingContext.

      For prepaid, due now is the 1st period. For postpaid, the first period is the current subscription period (which is 1 if the subscription is new). Note that for postpaid if the action is during the free trial period (period number = 0), the first period is the next subscription period.

      Parameters:
      periodNumber - the period number to check
      pricingContext - the current SubscriptionPricingContext
      Returns:
      whether the given period is the first period
    • isAdjustmentApplicableForPeriod

      protected boolean isAdjustmentApplicableForPeriod(@NonNull com.broadleafcommerce.order.common.domain.Adjustment adjustment, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable Integer period)
    • isAdjustmentApplicableForPeriod

      protected boolean isAdjustmentApplicableForPeriod(@NonNull @NonNull SubscriptionItemAdjustment adjustment, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable Integer period)
    • isAdjustmentApplicableForPeriod

      protected boolean isAdjustmentApplicableForPeriod(int adjustmentBeginPeriod, @Nullable Integer adjustmentEndPeriod, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable Integer period)
      Determines whether the given adjustment is applicable for the given period.

      For prepaid, due now is the 1st period, so the actual period is already incremented by 1. However in prepaid downgrade, the subscription remains on the current plan for the remaining period, so the adjustment isn't applied in the due now, so the actual period need to be subtracted by 1 in this case.

      For postpaid, there is no due now, so the period typically aligns. However, in the case of cancellation, there is due now, so the actual period needs to be incremented by 1.

      Parameters:
      adjustmentBeginPeriod - the configured begin period from the adjustment
      adjustmentEndPeriod - the configured end period from the adjustment
      pricingContext - the current SubscriptionPricingContext
      period - the period to check the adjustment against. Null for due now
      Returns:
      whether the adjustment is applicable for the given period
    • determineProratedUnitDiscountAmountForCustomFlow

      protected javax.money.MonetaryAmount determineProratedUnitDiscountAmountForCustomFlow(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineCreditedUnitDiscountAmount

      protected javax.money.MonetaryAmount determineCreditedUnitDiscountAmount(@NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the unit amount to be discounted from the credited unit amount.

      For example, if a $10 discount was previously applied to the subscription that costs $100, and assuming that the full $100 is being credited, the $10 discount should be deducted from the total credited amount, since the user paid $10 less.

      Parameters:
      adjustment - the SubscriptionItemAdjustment to determine the unit discount
      existingSubscriptionItemId - the existing SubscriptionItem.getId()
      period - the period to check the adjustment against. Null for due now
      pricingContext - the current SubscriptionPricingContext
      contextInfo - context surrounding the multi-tenant state
      Returns:
      the unit amount to be discounted from the credited unit amount
    • determineCreditedUnitDiscountAmountForModificationFlow

      protected javax.money.MonetaryAmount determineCreditedUnitDiscountAmountForModificationFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineCreditedDiscountUnitAmountForCancellationFlow

      protected javax.money.MonetaryAmount determineCreditedDiscountUnitAmountForCancellationFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineCreditedDiscountUnitAmountForCustomCancellationChargeStrategy

      protected javax.money.MonetaryAmount determineCreditedDiscountUnitAmountForCustomCancellationChargeStrategy(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineCreditedUnitDiscountAmountForCustomFlow

      protected javax.money.MonetaryAmount determineCreditedUnitDiscountAmountForCustomFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determinePriorUnbilledUnitDiscountAmount

      protected javax.money.MonetaryAmount determinePriorUnbilledUnitDiscountAmount(@NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determinePriorUnbilledUnitDiscountAmountForModificationFlow

      protected javax.money.MonetaryAmount determinePriorUnbilledUnitDiscountAmountForModificationFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determinePriorUnbilledDiscountUnitAmountForCurrentPeriod

      protected javax.money.MonetaryAmount determinePriorUnbilledDiscountUnitAmountForCurrentPeriod(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the discount amount that should be deducted from the customer's prior unbilled amount for the current period.

      For example in a postpaid scenario, if you modify the subscription in the middle of the billing cycle, the prior unbilled amount is the amount that the user has already consumed but not yet paid for prior to the modification. If the user received a $10 discount in the current period, that $10 should be prorated and deducted from the prior unbilled amount.

      In a cancel subscription scenario with CancellationPolicyDetail.isChargeForPreviouslyReceivedDiscountAmounts() being true, no discount is given, and the charge is added separately in determineChargeForPreviouslyDiscountedPeriodsForCurrentPeriod(SubscriptionItemAdjustmentPriceDetail, SubscriptionPricingContext, SubscriptionItemAdjustment, ContextInfo)

      Parameters:
      pricingContext - the current SubscriptionPricingContext
      adjustment - the SubscriptionItemAdjustment to determine the unit discount
      existingSubscriptionItemId - the existing SubscriptionItem.getId()
      contextInfo - context surrounding the multi-tenant state
      Returns:
      the discount amount that should be deducted from the customer's prior unbilled amount for the current period
    • determinePriorUnbilledDiscountUnitAmountForCancellationFlow

      protected javax.money.MonetaryAmount determinePriorUnbilledDiscountUnitAmountForCancellationFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the discount amount that should be deducted from the customer's prior unbilled amount for immediate cancellation scenario.

      Note that this amount can be negative indicating a charge for the received discount if CancellationPolicyDetail.isChargeForPreviouslyReceivedDiscountAmounts() for the current period.

      If you cancel the subscription in the middle of the billing cycle, the prior unbilled amount is the amount that the user has already consumed but not yet paid for prior to the cancellation. If the user received a $10 discount in the current period, that $10 should be prorated and deducted from the prior unbilled amount.

      Parameters:
      pricingContext - the current SubscriptionPricingContext
      adjustment - the SubscriptionItemAdjustment to determine the unit discount
      existingSubscriptionItemId - the existing SubscriptionItem.getId()
      contextInfo - context surrounding the multi-tenant state
      Returns:
      the discount amount that should be deducted from the customer's prior unbilled amount for the current period
    • determinePriorUnbilledDiscountUnitAmountForCustomCancellationStrategy

      protected javax.money.MonetaryAmount determinePriorUnbilledDiscountUnitAmountForCustomCancellationStrategy(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determinePriorUnbilledUnitDiscountAmountForCustomFlow

      protected javax.money.MonetaryAmount determinePriorUnbilledUnitDiscountAmountForCustomFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineProratedUnitAmountForCustomFlow

      protected javax.money.MonetaryAmount determineProratedUnitAmountForCustomFlow(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.cart.client.domain.CartItem parentCartItem, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Hook point to handle determining the prorated unit amount for an item during a non-default action flow.
      Parameters:
      parentCartItem - the parent cart item for the specified cart item. Usually, this is the item that has the dependent cart items. Will be null if the cart item is the root.
      cartItem - the child item whose price we're wanting to identify.
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      contextInfo - context surrounding the multi-tenant state
      Returns:
      The amount owed for the rest of the billing period based on how much of the billing period has elapsed at the time of the subscription action
      See Also:
    • determineProratedUnitAmountForCreateFlow

      protected javax.money.MonetaryAmount determineProratedUnitAmountForCreateFlow(@Nullable com.broadleafcommerce.cart.client.domain.CartItem parentCartItem, @NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • getFullUpFrontUnitAmount

      protected javax.money.MonetaryAmount getFullUpFrontUnitAmount(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • getTypicalRecurringUnitAmount

      protected javax.money.MonetaryAmount getTypicalRecurringUnitAmount(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determinePricePerDayForCurrentPeriod

      protected javax.money.MonetaryAmount determinePricePerDayForCurrentPeriod(@NonNull @NonNull javax.money.MonetaryAmount recurringSubtotal, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the price per day for the current period. Note: This considers the exact number of days that are in the current period to create a more accurate price-per-day calculation within the given period. In the case of a creation flow with an atypical bill date, this will consider the number of days in a full period prior to the atypical bill date.
      Parameters:
      recurringSubtotal - The typical subtotal for the period
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      contextInfo - context surrounding the multi-tenant state
      Returns:
      The price per day for a given period
    • determinePricePerDay

      protected javax.money.MonetaryAmount determinePricePerDay(@NonNull @NonNull javax.money.MonetaryAmount recurringSubtotal, @NonNull @NonNull PeriodDefinition periodDefinition, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the price per day for the given PeriodDefinition.
      Parameters:
      recurringSubtotal - The typical subtotal for the period
      periodDefinition - The PeriodDefinition to calculate the price per day for
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      contextInfo - context surrounding the multi-tenant state
      Returns:
      The price per day for a given period
    • determineProratedUnitAmountForModificationFlow

      protected javax.money.MonetaryAmount determineProratedUnitAmountForModificationFlow(@Nullable com.broadleafcommerce.cart.client.domain.CartItem parentCartItem, @NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the prorated unit amount for a subscription cart item for a modification flow (edit, upgrade, or downgrade).
      Parameters:
      parentCartItem - the parent cart item for the specified cart item. Usually, this is the item that has the dependent cart items. Will be null if the cart item is the root.
      cartItem - the child item whose price we're wanting to identify.
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      contextInfo - context surrounding the multi-tenant state
      Returns:
      the prorated amount for a subscription cart item for a modification flow (edit, upgrade, or downgrade).
    • determineProratedUnitAmountForCancellationFlow

      protected javax.money.MonetaryAmount determineProratedUnitAmountForCancellationFlow(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.cart.client.domain.CartItem parentCartItem, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the prorated amount for a subscription cart item for a cancellation flow. For DefaultCancellationStrategy.CANCEL_AUTO_RENEWAL and future periods, this will be 0. Otherwise, this will be determined by CancellationPolicyDetail.getChargeStrategy() and added to the upfront amount to charge the customer for cancelling.
      Parameters:
      cartItem - the child item whose price we're wanting to identify.
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      parentCartItem - the parent cart item for the specified cart item. Usually, this is the item that has the dependent cart items. Will be null if the cart item is the root.
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context surrounding the multi-tenant state
      Returns:
      the prorated amount for a subscription cart item for a cancellation flow.
    • determineProratedUnitDiscountAmountForCancellationFlow

      protected javax.money.MonetaryAmount determineProratedUnitDiscountAmountForCancellationFlow(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the prorated discount amount for a subscription cart item for a cancellation flow. F By default, this returns 0.
      Parameters:
      cartItem - the child item whose price we're wanting to identify.
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context surrounding the multi-tenant state
      Returns:
      the prorated discount amount for a subscription cart item for a cancellation flow.
    • determineProratedUnitAmountForImmediateCancellation

      protected javax.money.MonetaryAmount determineProratedUnitAmountForImmediateCancellation(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the prorated unit amount during an immediate cancellation request. By default, this is 0. Either the current period's amount is already paid or it should be considered part of the prior unbilled amount.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      contextInfo - context surrounding the multi-tenant state
      Returns:
      The prorated amount for a subscription being cancelled immediately.
    • determineProratedUnitAmountForCustomCancellationStrategy

      protected javax.money.MonetaryAmount determineProratedUnitAmountForCustomCancellationStrategy(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.cart.client.domain.CartItem parentCartItem, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Hook point for custom cancellation strategy values.
      Parameters:
      cartItem - the child item whose price we're wanting to identify.
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      parentCartItem - the parent cart item for the specified cart item. Usually, this is the item that has the dependent cart items. Will be null if the cart item is the root.
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context surrounding the multi-tenant state
      Returns:
      the prorated amount for a subscription cart item for a cancellation flow.
      See Also:
    • getExistingSubscriptionItemQuantity

      protected Integer getExistingSubscriptionItemQuantity(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • getExistingSubscriptionItemUnitPrice

      @Nullable protected javax.money.MonetaryAmount getExistingSubscriptionItemUnitPrice(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • isDecreaseInQuantity

      protected boolean isDecreaseInQuantity(@Nullable Integer existingSubscriptionItemQuantity, @NonNull @NonNull Integer cartItemQuantity)
    • determineProratedAmountBetweenActionAndNextBillDate

      protected javax.money.MonetaryAmount determineProratedAmountBetweenActionAndNextBillDate(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineProratedAmountBetweenActionAndNextBillDate

      protected javax.money.MonetaryAmount determineProratedAmountBetweenActionAndNextBillDate(@NonNull @NonNull javax.money.MonetaryAmount fullPeriodAmountToProrate, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the prorated amount between the action date and the next bill date for a given MonetaryAmount. This is only relevant for the SubscriptionPricingContext.getCurrentSubscriptionPeriod() since that's when the proration needs to be done.

      The logic intentionally defers to determineProratedAmountBetweenPeriodStartAndActionDate(MonetaryAmount, SubscriptionPricingContext, ContextInfo) and then subtracts the amount from the total amount. This is to avoid any potential, although unlikely, issues with division and rounding. Taking the subtraction approach ensures that the sum of the prorated amount between period start date and action date and the prorated amount between action date and next bill date is equal to the total amount, without having to worry about potential issues with rounding 2 different amounts separately.

      Note that if the current period is shortened and the period start date is changed, typically due to billing frequency change, the proration is directly calculated rather than deferring to determineProratedAmountBetweenPeriodStartAndActionDate(MonetaryAmount, SubscriptionPricingContext, ContextInfo).

      Parameters:
      fullPeriodAmountToProrate - the full-period total MonetaryAmount to prorate
      pricingContext - the current SubscriptionPricingContext
      contextInfo - context surrounding the multi-tenant state
      Returns:
      the prorated amount between the action date and the next bill date for the given
    • determineProratedAmountBetweenPeriodStartAndActionDate

      protected javax.money.MonetaryAmount determineProratedAmountBetweenPeriodStartAndActionDate(@NonNull @NonNull javax.money.MonetaryAmount fullPeriodAmountToProrate, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the prorated amount between the period start date and action date for a given MonetaryAmount. This is only relevant for the SubscriptionPricingContext.getCurrentSubscriptionPeriod() since that's when the proration needs to be done.
      Parameters:
      fullPeriodAmountToProrate - the total MonetaryAmount to prorate
      pricingContext - the current SubscriptionPricingContext
      contextInfo - context surrounding the multi-tenant state
      Returns:
      the prorated amount between the period start date and action date
      See Also:
    • determineProratedAmountForCurrentPeriod

      protected javax.money.MonetaryAmount determineProratedAmountForCurrentPeriod(@NonNull @NonNull javax.money.MonetaryAmount fullPeriodAmountToProrate, @NonNull @NonNull SubscriptionPricingContext pricingContext, long numberOfDaysToProrate, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineProratedAmount

      protected javax.money.MonetaryAmount determineProratedAmount(@NonNull @NonNull javax.money.MonetaryAmount fullPeriodAmountToProrate, PeriodDefinition periodDefinition, @NonNull @NonNull SubscriptionPricingContext pricingContext, long numberOfDaysToProrate, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineCreditedUnitAmount

      protected javax.money.MonetaryAmount determineCreditedUnitAmount(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      For a SubscriptionItemPriceDetail, determines the unit amount to credit to the user during a subscription flow. This is based on the amount the user may have already paid for the currently billing period prior to modification of the subscription.

      Typically, the user is only credited an amount when they have prepaid during the current billing period and are editing or upgrading their subscription. Additionally, this typically only applies to the due now pricing rather than to any subsequent periods.

      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context information around multi-tenant state
      Returns:
      The amount to credit to the user during a subscription flow.
      See Also:
    • determineCreditedUnitAmountForCustomFlow

      protected javax.money.MonetaryAmount determineCreditedUnitAmountForCustomFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Hook point for non-default action flows.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context information around multi-tenant state
      Returns:
      The amount to credit to the user during a subscription flow.
      See Also:
    • determineCreditedUnitAmountForCreateFlow

      protected javax.money.MonetaryAmount determineCreditedUnitAmountForCreateFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the unit amount to credit to the user during a create flow. This is typically zero as there is no prior billing period.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being created
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context information around multi-tenant state
      Returns:
      The amount to credit to the user during a create flow.
      See Also:
    • determineCreditedUnitAmountForCancellationFlow

      protected javax.money.MonetaryAmount determineCreditedUnitAmountForCancellationFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the unit amount to credit to the user during a cancellation flow. This is based on the amount the user may have already paid for the currently billing period prior to cancelling the subscription. Typically, this is only relevant for DefaultSubscriptionPaymentStrategy.PREPAID subscriptions.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being cancelled
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context information around multi-tenant state
      Returns:
      The amount to credit to the user during a cancellation flow.
      See Also:
    • determineCreditedUnitAmountForCustomCancellationChargeStrategy

      protected javax.money.MonetaryAmount determineCreditedUnitAmountForCustomCancellationChargeStrategy(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Hook point for custom cancellation charge strategies. This is typically only relevant when the subscription is in the grace period or the user should not be charged for the remainder of the term and they have prepaid for this period.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being cancelled
      contextInfo - context information around multi-tenant state
      Returns:
      The amount to credit to the user during a cancellation flow.
      See Also:
    • determineCreditedUnitAmountForModificationFlow

      protected javax.money.MonetaryAmount determineCreditedUnitAmountForModificationFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the unit amount to credit to the user during a modification flow (e.g., edit, upgrade, downgrade). This is based on the amount the user may have already paid for the currently billing period prior to cancelling the subscription.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being modified
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context information around multi-tenant state
      Returns:
      The amount to credit to the user during a modification flow.
      See Also:
    • determineCreditedUnitAmountForCurrentPeriod

      protected javax.money.MonetaryAmount determineCreditedUnitAmountForCurrentPeriod(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the amount to credit to the customer based on when in the current billing period a pricing request occurs. Generally only relevant for prepaid subscriptions and during modification or cancellation flows. The customer will be credited for what part of the period they have already paid for but will not be using due to a modification or cancellation.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being modified
      contextInfo - context information around multi-tenant state
      Returns:
      The amount to credit to the customer.
    • determineCreditedUnitAmountForCurrentPeriodForBillingFrequencyChange

      protected javax.money.MonetaryAmount determineCreditedUnitAmountForCurrentPeriodForBillingFrequencyChange(@NonNull @NonNull javax.money.MonetaryAmount unitAmountToProrate, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineCreditedUnitDiscountAmountForCurrentPeriod

      protected javax.money.MonetaryAmount determineCreditedUnitDiscountAmountForCurrentPeriod(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the discount amount that should be deducted from the customer's credited amount based on when in the current billing period a pricing request occurs. Generally only relevant for prepaid subscriptions and during modification or cancellation flows when the customer will be credited for what part of the period they have already paid for but will not be using due to a modification or cancellation.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The existing SubscriptionItem.getId() where the adjustment is targeting
      contextInfo - context information around multi-tenant state
      Returns:
      The discount amount
    • determinePriorUnbilledUnitAmount

      protected javax.money.MonetaryAmount determinePriorUnbilledUnitAmount(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      For a SubscriptionItemPriceDetail, determines the unit amount that has not been billed for the current billing period at the time of the current subscription action. This is the amount that would have been paid on the next billing date. This will be calculated based on the previously elapsed days in the billing period and is the complement to the prorated amount and is added to it to determine the full amount owed.

      This typically only applies when the subscription is postpaid for edits, upgrades, and downgrades.

      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context information around multi-tenant state
      Returns:
      The amount that has not been billed for the current billing period.
    • determinePriorUnbilledUnitAmountForCustomFlow

      protected javax.money.MonetaryAmount determinePriorUnbilledUnitAmountForCustomFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Hook point for non-default action flows.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context information around multi-tenant state
      Returns:
      The amount that has not been billed for the current billing period.
      See Also:
    • determinePriorUnbilledUnitAmountForCreateFlow

      protected javax.money.MonetaryAmount determinePriorUnbilledUnitAmountForCreateFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the unit amount that has not been billed for the current billing period during a create flow. Typically, this should be zero.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context information around multi-tenant state
      Returns:
      The amount that has not been billed for the current billing period.
    • determinePriorUnbilledUnitAmountForCancellationFlow

      protected javax.money.MonetaryAmount determinePriorUnbilledUnitAmountForCancellationFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the unit amount that has not been billed for the current billing period during a cancellation flow. This will include the remainder of the term's cost if applicable.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context information around multi-tenant state
      Returns:
      The amount that has not been billed for the current billing period.
      See Also:
    • determinePriorUnbilledUnitAmountForCustomCancellationStrategy

      protected javax.money.MonetaryAmount determinePriorUnbilledUnitAmountForCustomCancellationStrategy(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Hook point for custom cancellation strategy values.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context information around multi-tenant state
      Returns:
      The amount that has not been billed for the current billing period.
      See Also:
    • determinePriorUnbilledUnitAmountForImmediateCancellation

      protected javax.money.MonetaryAmount determinePriorUnbilledUnitAmountForImmediateCancellation(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the prior unbilled amount to charge the customer for an DefaultCancellationStrategy.IMMEDIATE cancellation. This typically only matters for DefaultSubscriptionPaymentStrategy.POSTPAID subscriptions or subscriptions with terms. It typically also only applies for the upfront charge and not future periods since there won't be any future periods.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      contextInfo - additional sandbox and multitenant info
      Returns:
      The prior unbilled amount to charge the customer for an DefaultCancellationStrategy.IMMEDIATE cancellation.
    • determineUnbilledUnitAmountForCurrentPeriodDuringCancellation

      protected javax.money.MonetaryAmount determineUnbilledUnitAmountForCurrentPeriodDuringCancellation(@NonNull @NonNull SubscriptionPricingContext pricingContext, String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the amount to bill the customer for the current period in which a cancellation request is received. This takes into account the charge strategy only when in the grace period or CancellationPolicyDetail.isChargeForRemainderOfTerms() is false.

      "Remainder of terms" is considered to be anything after the DefaultSubscriptionActionFlow.CANCEL action, so when CancellationPolicyDetail.isChargeForRemainderOfTerms() is true, the prior unbilled amount only includes the charge for the period prior to cancellation (between period start date and the action/cancel date). The charge for period after cancellation (between action/cancel date and the next bill date) is included separately in SubscriptionItemPriceDetail.getRemainderOfTermsUnitAmount().

      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      contextInfo - additional sandbox and multitenant info
      Returns:
      The prior unbilled amount for the current period to charge the customer for an DefaultCancellationStrategy.IMMEDIATE cancellation.
      See Also:
    • determineUnbilledUnitDiscountAmountForCurrentPeriodDuringCancellation

      protected javax.money.MonetaryAmount determineUnbilledUnitDiscountAmountForCurrentPeriodDuringCancellation(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineDiscountForRemainderOfTerm

      protected javax.money.MonetaryAmount determineDiscountForRemainderOfTerm(@NonNull @NonNull SubscriptionItemAdjustmentPriceDetail adjustmentDetail, @NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the discounts to be applied to the remainder of the terms charge if you are being charged for the remainder of the terms, unless full price is charged for the remainder of terms.
      Parameters:
      adjustmentDetail - the current SubscriptionItemAdjustmentPriceDetail that the discount is being calculated for
      pricingContext - the current SubscriptionPricingContext
      adjustment - the SubscriptionItemAdjustment being applied
      period - the period to calculate the discount for
      contextInfo - additional sandbox and multitenant info
      Returns:
      the discount amount for the remainder of the terms
    • determineDiscountForRemainderOfTermFuturePeriods

      protected javax.money.MonetaryAmount determineDiscountForRemainderOfTermFuturePeriods(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the discounts to be applied to the remainder of the terms charge if you are being charged for the remainder of the terms, unless full price is charged for the remainder of terms.

      Note that this amount is only for future periods and does not include the current period.
      Parameters:
      pricingContext - the current SubscriptionPricingContext
      adjustment - the SubscriptionItemAdjustment being applied
      contextInfo - additional sandbox and multitenant info
      Returns:
      the discount amount for the remainder of the terms
    • determinePeriodsLeftToReceiveDiscount

      protected long determinePeriodsLeftToReceiveDiscount(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the number of periods left to receive discount for calculating the remainder of terms discount for future periods.

      The periodsLeftToReceiveDiscount is subtracted by 1 to exclude the current period only if the periodsLeftToReceiveDiscount is derived from totalAdjustmentPeriod, since current period is already excluded from periodsLeftInTerm.

      Parameters:
      pricingContext - the current SubscriptionPricingContext
      adjustment - the SubscriptionItemAdjustment being applied
      contextInfo - additional sandbox and multitenant info
      Returns:
      the number of periods left to receive discount for calculating the remainder of terms discount for future periods
    • determineDiscountForRemainderOfTermCurrentPeriod

      protected javax.money.MonetaryAmount determineDiscountForRemainderOfTermCurrentPeriod(@NonNull @NonNull SubscriptionItemAdjustmentPriceDetail adjustmentDetail, @NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the discounts to be applied to the remainder of the terms charge for the current period if you are being charged for the remainder of the terms, unless full price is charged for the remainder of terms.

      "Remainder of terms" is considered to be anything after the DefaultSubscriptionActionFlow.CANCEL action, so the discount for the current period is the period after cancellation (between action/cancel date and the next bill date).

      Parameters:
      adjustmentDetail - the current SubscriptionItemAdjustmentPriceDetail that the discount is being calculated for
      pricingContext - the current SubscriptionPricingContext
      adjustment - the SubscriptionItemAdjustment being applied
      contextInfo - additional sandbox and multitenant info
      Returns:
      the discount amount for the remainder of the terms for the current period
    • determineChargeForPreviouslyDiscountedPeriods

      protected javax.money.MonetaryAmount determineChargeForPreviouslyDiscountedPeriods(@NonNull @NonNull SubscriptionItemAdjustmentPriceDetail adjustmentDetail, @NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the amount to charge the customer for the previously received discounts in previous periods if CancellationPolicyDetail.isChargeForPreviouslyReceivedDiscountAmounts() is true. The discount to charge for the current period is calculated within the prior unbilled calculation, since that needs to be prorated based on the days that have been used.

      Note that this amount is not negated since it will be added separately as part of the prior unbilled amount.

      Parameters:
      adjustmentDetail - the current SubscriptionItemAdjustmentPriceDetail that the discount is being calculated for
      pricingContext - the current SubscriptionPricingContext
      adjustment - the SubscriptionItemAdjustment being charged
      period - the period to calculate the charge for
      contextInfo - additional sandbox and multitenant info
      Returns:
      the previously discount amount to charge
    • determineChargeForPreviouslyDiscountedPeriodsBeforeCurrentPeriod

      protected javax.money.MonetaryAmount determineChargeForPreviouslyDiscountedPeriodsBeforeCurrentPeriod(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the amount to charge the customer for the previously received discounts in previous periods.

      Note that this amount does not include the current period and is not negated since it will be added separately as part of the prior unbilled amount.

      Parameters:
      pricingContext - the current SubscriptionPricingContext
      adjustment - the SubscriptionItemAdjustment being charged
      contextInfo - additional sandbox and multitenant info
      Returns:
      the previously discount amount to charge
    • determineChargeForPreviouslyDiscountedPeriodsForCurrentPeriod

      protected javax.money.MonetaryAmount determineChargeForPreviouslyDiscountedPeriodsForCurrentPeriod(@NonNull @NonNull SubscriptionItemAdjustmentPriceDetail adjustmentDetail, @NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the amount to charge the customer for the previously received discounts in the current period.

      Note that this amount is not negated since it will be added separately as part of the prior unbilled amount.

      Parameters:
      adjustmentDetail - the current SubscriptionItemAdjustmentPriceDetail that the discount is being calculated for
      pricingContext - the current SubscriptionPricingContext
      adjustment - the SubscriptionItemAdjustment being charged
      contextInfo - additional sandbox and multitenant info
      Returns:
      the previously discount amount to charge for the current period
    • determineUnbilledDiscountUnitAmountForCurrentPeriodDuringCancellationForCustomChargeStrategy

      protected javax.money.MonetaryAmount determineUnbilledDiscountUnitAmountForCurrentPeriodDuringCancellationForCustomChargeStrategy(@NonNull @NonNull SubscriptionPricingContext pricingContext, @NonNull @NonNull SubscriptionItemAdjustment adjustment, @Nullable String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • determineUnbilledUnitAmountForCurrentPeriodDuringCancellationForCustomChargeStrategy

      protected javax.money.MonetaryAmount determineUnbilledUnitAmountForCurrentPeriodDuringCancellationForCustomChargeStrategy(@NonNull @NonNull SubscriptionPricingContext pricingContext, String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Hook point for custom charge strategies when inside a grace period to determine the unbilled unit amount for the current period.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      contextInfo - additional sandbox and multitenant info
      Returns:
      The prior unbilled amount for the current period to charge the customer for an DefaultCancellationStrategy.IMMEDIATE cancellation.
      See Also:
    • determineUnitAmountToChargeForRemainderOfTermCurrentPeriod

      protected javax.money.MonetaryAmount determineUnitAmountToChargeForRemainderOfTermCurrentPeriod(@NonNull @NonNull SubscriptionPricingContext pricingContext, String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the unit amount (non-discounted) to charge the customer for the current period when they cancel their subscription before the end of the term and when the cancellation strategy is DefaultCancellationStrategy.IMMEDIATE and CancellationPolicyDetail.isChargeForRemainderOfTerms().

      "Remainder of terms" is considered to be anything after the DefaultSubscriptionActionFlow.CANCEL action, so the charge for the current period is the period after cancellation (between action/cancel date and the next bill date).

      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      contextInfo - additional sandbox and multitenant info
      Returns:
      The unit amount (non-discounted) to charge the customer for the current period
      See Also:
    • determineUnitAmountToChargeForRemainderOfTermFuturePeriods

      protected javax.money.MonetaryAmount determineUnitAmountToChargeForRemainderOfTermFuturePeriods(@NonNull @NonNull SubscriptionPricingContext pricingContext, String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the remaining amount (non-discounted) to charge the customer when they cancel their subscription before the end of the term and when the cancellation strategy is DefaultCancellationStrategy.IMMEDIATE. Uses CancellationPolicyDetail.isChargeForRemainderOfTerms() and whether the customer is in the grace period: If the former is false or the latter is true, then there is no additional charge. Additionally, if there are no terms, there is no additional charge.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      contextInfo - additional sandbox and multitenant info
      Returns:
      The remaining amount (non-discounted) to charge the customer.
      See Also:
    • determinePriorUnbilledUnitAmountForModificationFlow

      protected javax.money.MonetaryAmount determinePriorUnbilledUnitAmountForModificationFlow(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable Integer period, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the unit amount that has not been billed for the current billing period during a modification flow (e.g., edit, upgrade, or downgrade). This typically only matters for postpaid subscriptions.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      period - the subscription billing period which we're identifying the price for. Will be null for due now amounts.
      contextInfo - context information around multi-tenant state
      Returns:
      The amount that has not been billed for the current billing period.
    • determinePriorUnbilledUnitAmountForCurrentPeriod

      protected javax.money.MonetaryAmount determinePriorUnbilledUnitAmountForCurrentPeriod(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the prior unbilled unit amount for the current billing period. The typically only matters for DefaultSubscriptionPaymentStrategy.POSTPAID subscriptions.
      Parameters:
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      existingSubscriptionItemId - The ID of the existing subscription being acted upon
      contextInfo - context information around multi-tenant state
      Returns:
      The prior unbilled amount for the current billing period.
    • determineProratedAmountFromOldPeriodStartDateToActionDateForBillingFrequencyChange

      protected javax.money.MonetaryAmount determineProratedAmountFromOldPeriodStartDateToActionDateForBillingFrequencyChange(@NonNull @NonNull javax.money.MonetaryAmount unitAmountToProrate, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines the prorated amount for the period between the original period start date to the action date for when the billing frequency changes.

      This is typically used to calculate the prior unbilled amount or prior unbilled discount amount for POSTPAID subscription when its billing frequency is changed

      Parameters:
      unitAmountToProrate - the unit amount to prorate
      pricingContext - the SubscriptionPricingContext
      contextInfo - Additional sandbox and multitenant info
      Returns:
      the prorated amount for the period between the original period start date to the action date for when the billing frequency changes.
    • getDaysBetweenPeriodStartAndActionDate

      protected long getDaysBetweenPeriodStartAndActionDate(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • calculateProratedAmountTotal

      protected <T extends SubscriptionItemPriceDetail> javax.money.MonetaryAmount calculateProratedAmountTotal(@NonNull @NonNull List<T> itemDetails, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      For a SubscriptionPriceResponse, determines the amount owed for the rest of the billing period based on how much of the billing period has elapsed at the time of the subscription action.

      This will total the amounts from the itemDetails.

      Parameters:
      itemDetails - The already populated SubscriptionItemPriceDetails for each item in a subscription, including the root and its dependents.
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      contextInfo - Additional sandbox and multitenant info
      Returns:
      The amount owed for the rest of the billing period.
    • calculateCreditedAmountTotal

      protected <T extends SubscriptionItemPriceDetail> javax.money.MonetaryAmount calculateCreditedAmountTotal(@NonNull @NonNull List<T> itemDetails, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      For a SubscriptionPriceResponse, determines the amount to credit to the user during a subscription flow. This is based on the amount the user may have already paid for the currently billing period prior to subscription of the subscription.

      This will total the amounts from the itemDetails.

      Parameters:
      itemDetails - The already populated SubscriptionItemPriceDetails for each item in a subscription, including the root and its dependents.
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      contextInfo - Additional sandbox and multitenant info
      Returns:
      The amount to credit to the user during a subscription flow
    • calculatePriorUnbilledAmountTotal

      protected <T extends SubscriptionItemPriceDetail> javax.money.MonetaryAmount calculatePriorUnbilledAmountTotal(@NonNull @NonNull List<T> itemDetails, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      For a SubscriptionPriceResponse, determines the amount that has not been billed for the current billing period at the time of the current subscription action. This is the amount that would have been paid on the next billing date. This will be calculated based on the previously elapsed days in the billing period and is the complement to the prorated amount and is added to it to determine the full amount owed.

      This will total the amounts from the itemDetails.

      Parameters:
      itemDetails - The already populated SubscriptionItemPriceDetails for each item in a subscription, including the root and its dependents.
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      contextInfo - Additional sandbox and multitenant info
      Returns:
      the amount that has not been billed for the current billing period at the time of the current subscription action
    • getAmountWithDependentItems

      protected <T extends SubscriptionItemPriceDetail> javax.money.MonetaryAmount getAmountWithDependentItems(@NonNull T itemPriceDetail, @NonNull @NonNull String priceDetailType, @NonNull @NonNull List<T> allItemPriceDetails, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • getAdjustmentAmount

      protected <T extends SubscriptionItemAdjustmentPriceDetail> javax.money.MonetaryAmount getAdjustmentAmount(@NonNull T itemAdjustmentPriceDetail, @NonNull @NonNull String priceDetailType, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Gets the adjustment amount from the given SubscriptionItemAdjustmentPriceDetail and priceDetailType.
      Type Parameters:
      T - the type of SubscriptionItemAdjustmentPriceDetail
      Parameters:
      itemAdjustmentPriceDetail - the SubscriptionItemAdjustmentPriceDetail to get the adjustment amount from
      priceDetailType - the type of price detail to get the adjustment amount for
      pricingContext - the SubscriptionPricingContext in which this operation
      contextInfo - context information around multi-tenant state
      Returns:
      the adjustment amount from the given SubscriptionItemAdjustmentPriceDetail
    • getAmountGetter

      protected Function<SubscriptionItemPriceDetail,javax.money.MonetaryAmount> getAmountGetter(String priceDetailType)
      Based on the provided DefaultSubscriptionPriceDetailType, identifies the relevant getter on the SubscriptionItemPriceDetail.
      Parameters:
      priceDetailType - the relevant DefaultSubscriptionPriceDetailType
      Returns:
      a SubscriptionItemPriceDetail getter use to gather the price identified by the DefaultSubscriptionPriceDetailType
    • getDiscountAmountGetter

      protected Function<SubscriptionItemAdjustmentPriceDetail,javax.money.MonetaryAmount> getDiscountAmountGetter(String priceDetailType)
    • getDependentItems

      protected <T extends SubscriptionItemPriceDetail> List<T> getDependentItems(@NonNull T parentItem, @NonNull @NonNull List<T> allItemPriceDetails)
    • getItemQuantity

      protected <T extends SubscriptionItemPriceDetail> Integer getItemQuantity(@NonNull T itemPriceDetail, @NonNull @NonNull String priceDetailType)
    • getItemAdjustmentQuantity

      protected <T extends SubscriptionItemAdjustmentPriceDetail> int getItemAdjustmentQuantity(@NonNull T itemAdjustmentDetail, @NonNull @NonNull String priceDetailType)
      Determines the quantity to be used for the given SubscriptionItemAdjustmentPriceDetail total discount calculation.

      Different priceDetailTypes affect the origin of the quantity. For example, credited discount amount should use the existing subscription item adjustment quantity prior the modification, while prorated discount amount should use the current adjustment quantity.

      Type Parameters:
      T - the type of SubscriptionItemAdjustmentPriceDetail
      Parameters:
      itemAdjustmentDetail - the SubscriptionItemAdjustmentPriceDetail to determine the quantity for
      priceDetailType - the type of price detail to determine the quantity for
      Returns:
      the quantity to be used for the given SubscriptionItemAdjustmentPriceDetail total discount calculation
    • shouldBuildItemDetailsForRemovedSubscriptionItems

      protected boolean shouldBuildItemDetailsForRemovedSubscriptionItems(@Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Declares if SubscriptionItemPriceDetail records should be constructed for subscription items that have been removed according to the current state of the cart's items. For edits & upgrades of prepaid subscriptions, removed subscription items will be processed at the end of the period. Therefore, they should not be included for due-now pricing. For modification actions against postpaid subscriptions, the items should be included, so that any relevant unbilled amounts can be identified.
      Parameters:
      period - The subscription period that's being considered. When considering the "due now" price, this will be null.
      pricingContext - The SubscriptionPricingContext in which this operation is occurring
      contextInfo - context surrounding the multi-tenant state
      Returns:
      Declares if SubscriptionItemPriceDetail records should be constructed for subscription items that have been removed according to the current state of the cart's items.
    • buildItemDetailsForRemovedSubscriptionItems

      protected <T extends SubscriptionItemPriceDetail> List<T> buildItemDetailsForRemovedSubscriptionItems(@Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • buildItemDetailForRemovedSubscriptionItem

      protected <T extends SubscriptionItemPriceDetail> T buildItemDetailForRemovedSubscriptionItem(@NonNull @NonNull SubscriptionItem removedSubscriptionItem, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • populateActionPriceDetails

      protected SubscriptionPriceResponse populateActionPriceDetails(@NonNull @NonNull SubscriptionPriceResponse response, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • buildActionPriceDetails

      protected List<SubscriptionActionPriceDetail> buildActionPriceDetails(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem subscriptionRootItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • buildActionPriceDetailsForDependentCartItems

      protected List<SubscriptionActionPriceDetail> buildActionPriceDetailsForDependentCartItems(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • buildActionPriceDetail

      protected SubscriptionActionPriceDetail buildActionPriceDetail(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem cartItem, @Nullable com.broadleafcommerce.cart.client.domain.CartItem parentCartItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • buildActionPriceDetailsForRemovedSubscriptionItems

      protected List<SubscriptionActionPriceDetail> buildActionPriceDetailsForRemovedSubscriptionItems(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • buildActionPriceDetailForRemovedSubscriptionItem

      protected SubscriptionActionPriceDetail buildActionPriceDetailForRemovedSubscriptionItem(@NonNull @NonNull SubscriptionItem removedSubscriptionItem, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • getExistingDiscountTotal

      protected javax.money.MonetaryAmount getExistingDiscountTotal(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable String existingSubscriptionItemId, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Gets the existing discount total for the given SubscriptionItem.
      Parameters:
      pricingContext - the SubscriptionPricingContext in which this operation is in
      existingSubscriptionItemId - the ID of the existing subscription item
      contextInfo - context information around multi-tenant state
      Returns:
      the existing discount total for the given SubscriptionItem
    • buildEstimatedFuturePayments

      protected List<EstimatedFuturePayment> buildEstimatedFuturePayments(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • buildEstimatedFuturePayment

      protected EstimatedFuturePayment buildEstimatedFuturePayment(@Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • populatePeriodAndBillDates

      protected void populatePeriodAndBillDates(@NonNull @NonNull EstimatedFuturePayment estimatedFuturePayment, @Nullable Integer period, @NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • getParentItemQuantity

      protected int getParentItemQuantity(@Nullable com.broadleafcommerce.cart.client.domain.CartItem parentCartItem)
    • getCartItemWithDependentItems

      protected List<com.broadleafcommerce.cart.client.domain.CartItem> getCartItemWithDependentItems(@NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem subscriptionRootItem)
    • determineRemovedAdjustments

      protected List<RemovedAdjustment> determineRemovedAdjustments(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Determines which Adjustments have been removed due to modifications to an existing Subscription.
      Parameters:
      pricingContext - Contains relevant context for the pricing operation
      contextInfo - Additional sandbox and multitenant info
      Returns:
      RemovedAdjustments for any removed Adjustments.
    • getExistingSubscriptionAdjustments

      protected Stream<Adjustment> getExistingSubscriptionAdjustments(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Gets all the existing Adjustments from the existing Subscription and its items.
      Parameters:
      pricingContext - Contains relevant context for the pricing operation
      contextInfo - Additional sandbox and multitenant info
      Returns:
      All the existing Adjustments from the existing Subscription and its items.
    • getCurrentSubscriptionAdjustments

      protected Stream<com.broadleafcommerce.order.common.domain.Adjustment> getCurrentSubscriptionAdjustments(@NonNull @NonNull SubscriptionPricingContext pricingContext, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Gets all the current or new subscription Adjustments from the current Cart and CartItem.
      Parameters:
      pricingContext - Contains relevant context for the pricing operation
      contextInfo - Additional sandbox and multitenant info
      Returns:
      All the current or new subscription Adjustments from the current Cart and CartItem.
    • flattenDependentCartItems

      protected List<com.broadleafcommerce.cart.client.domain.CartItem> flattenDependentCartItems(@NonNull @NonNull List<com.broadleafcommerce.cart.client.domain.CartItem> accumulator, @NonNull @NonNull com.broadleafcommerce.cart.client.domain.CartItem parentItem)
      Flattens the dependents and sub-dependents etc. of a given CartItem into a single list.
      Parameters:
      accumulator - The flat list.
      parentItem - The next CartItem whose dependents to add to accumulator.
      Returns:
      The flat list.
    • buildRemovedAdjustment

      protected RemovedAdjustment buildRemovedAdjustment(@NonNull @NonNull List<? extends Adjustment> adjustments)
      Builds a RemovedAdjustment for the given Adjustment that was lost due to modifications to an existing Subscription. Accumulates the total adjusted value lost due to the adjustment being lost across the entire subscription.
      Parameters:
      adjustments - All instances of an Adjustments across an existing Subscription. These should share the same Adjustment.getAdjustmentRef().
      Returns:
      A RemovedAdjustment.
    • getSubscriptionProvider

    • getTypeFactory

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

      protected CancellationPolicyProvider<CancellationPolicy> getCancellationPolicyProvider()
    • getSubscriptionOperationUtils

      protected SubscriptionOperationUtils getSubscriptionOperationUtils()
    • getPricingProperties

      protected SubscriptionPricingProperties getPricingProperties()
    • getCustomerProvider

      protected CustomerProvider<FilteredAccounts> getCustomerProvider()
    • getWorkflowProvider

      protected com.broadleafcommerce.orchestration.service.provider.external.WorkflowProvider getWorkflowProvider()