Broadleaf Microservices
  • v1.0.0-latest-prod

Add and Update Cart Item Components

This section generally speaks to the components that the CartOperationService invokes when processing an add and update cart item request. For more details on how these operations differ for specific types of products, see the Cart Operations for Specific Product Types section.

The following diagram illustrates the add-to-cart flow at a high level with update being similar:

Add to Cart Sequence Diagram

Description:

  1. Request is sent from the client to create the cart, or add to an existing cart

  2. If creating a new cart, the controller delegates to CartOperationService to create a new empty cart.

  3. If adding to an existing cart, the CartResolverService is used by the controller to resolve the cart by ID, if it exists.

  4. The CartOperationService then executes the add item request which

    1. Retrieves product information for all items added to the cart

    2. Hydrates product information onto the appropriate cart items using CartItemCatalogInformationService

    3. Validates cart item configurations using CartItemConfigurationService

    4. Validates inventory availability for all items

    5. Handles merging or rejecting similar items using CartItemMergingService

    6. Sets any cart attributes included in the add request

    7. Assigns items to FulfillmentGroups, creating those groups as necessary

    8. Prices the cart

      • This process is fairly complicated in itself and has been summarized in the diagram in several steps

        1. Price the cart (get merchandise prices)

        2. Apply order and order item offers/discounts

        3. Price fulfillment

        4. Apply fulfillment and fulfillment item offers/discounts

        5. Calculate totals

          1. Subtotal

          2. Fulfillment total

          3. Total before tax

          4. Total after tax

      • See document on cart pricing

    9. Persists the cart

CartItemCatalogInformationService

Overview

Service responsible for mapping CatalogItem information onto CartItems. By default, this maps the details from Broadleaf’s Product and Variant domains.

Default Implementation Details

DefaultCartItemCatalogInformationService is the default implementation of CartItemCatalogInformationService. It handles mapping properties directly from products onto cart items. It also runs any configured CartItemProductMappers to map properties from products and variants that are not required by default.

However, it also relies on BroadleafProductService to handle the following:

  • Determining which Variant on the Product DTO matches a cart item

  • Determining which IncludedProduct or ItemChoice matches a dependent cart item

This is because CartOperationService will retrieve all of the related CatalogItems and their full hierarchies before calling CartItemCatalogInformationService. Then, it passes in the matching catalog item with its entire hierarchy without further narrowing since catalog item info can be inherited by its subdomains (e.g. Product information can be inherited by it’s Variants, IncludedProducts, and ItemChoice ProductOptions).

This creates a complication when CartItems match specific Variants since something must now determine which Variant on the Product DTO to hydrate information from. Likewise for dependent CartItems that match IncludedProducts or ItemChoices. BroadleafProductService provides a centralized location for handling these deeper hierarchical data for Product.

CartItemProductMappers

CartItemProductMappers provide a configurable way to define which properties of a product or variant are mapped to which properties of a cart item. This is in addition to the default mappings provided by CartItemCatalogInformationService for required properties. PropertyDrivenCartItemProductMapper is the only default implementation of CartItemProductMapper. It reads mappings from CartItemMappingProperties.

Example of configuring additional mappings:
broadleaf:
  cartoperation:
    mapping:
      cartitem:
        productMappings:
          - attributeName: 'productUri'
            valuePath: '$.uri'
          - attributeName: 'productDescription'
            valuePath: '$.description'
          - attributeName: 'categoryIds'
            valuePath: '$.parentCategories[*].id'
          - attributeName: 'categoryNames'
            valuePath: '$.parentCategories[*].name'
        variantMappings:
          ...

BroadleafProductService

Service that handles operations involving the hierarchical data for complex products, e.g., products with variants, included products, or item-choice product options. In particular it handles the following:

  • Determining which Variant on the Product DTO matches a cart item

  • Determining which IncludedProduct or ItemChoice matches a dependent cart item

CartItemConfigurationService

Overview

Service that handles hydration and validation for the hierarchical data of complex products, e.g., products with variants, included products, or item-choice product options. In particular it handles the following:

  • Hydrating IncludedProduct or ItemChoice info onto CartItems

  • Validating CartItem and dependent CartItem configurations, e.g.,

    • They have all of the require attributes

    • All attributes have valid values

    • They have a positive quantity or meet any min or max quantity requirements if applicable

DefaultCartItemConfigurationService makes use of several other configuration services for particular domains:

  • IncludedProductConfigurationService for populating IncludedProduct info on CartItems and validating them

  • ItemChoiceConfigurationService for populating ItemChoice ProductOption info on CartItems and validating them

  • AttributeChoiceConfigurationService for validating AttributeChoice ProductOption info on CartItems

Validation Error Messaging

Validation error messages are made accessible to API callers and auditors through one of the following properties of CartItem depending on what produced the errors:

  • globalConfigErrors: List of global configuration errors.

  • attributeConfigErrors: Map of configuration errors related to the item’s attribute choice values that are derived from AttributeChoice ProductOptions, where the key is the attribute name: COLOR, SIZE, etc.

  • dependentItemConfigErrors: Map of configuration errors related to the item’s dependent cart items where the key is the item’s identifier, e.g., a ItemChoice#choiceKey.

Each error is an object with an errorCode and an errorMessage string. DefaultCartItemConfigurationService and its related configuration services make use of a Spring’s MessageSource to provide localized error messages so that these messages can be shown directly to frontend users. Otherwise, the caller can use the errorCode. The message keys and their default values are as follows:

cartItem.configError.genericError=The item you added to the cart was not configured correctly. Please correct the errors and try again.
cartItem.configError.nonPositiveQuantity=Cannot add an item to the cart with a quantity less than 1.
cartItem.configError.nonPositiveDependentItemQuantity=Cannot add an item to the cart with a quantity less than 1.
cartItem.configError.requiredAttributeMissing={0} is required
cartItem.configError.noMatchingAllowedValue={0} does not have a valid value
cartItem.configError.noVariantFound=The selected combination of options is invalid.
cartItem.configError.requiredAttributesMissingOnItem=Some of the required options are missing.
cartItem.configError.dependentItems.quantity.min=Must select at least {0, number}
cartItem.configError.dependentItems.quantity.max=Must select no more than {0, number}
cartItem.configError.mismatchedDependentItemsFoundOnItem=Mismatched items found on Cart Item and have been removed.
cartItem.configError.misconfiguredDependentItems=Some of the items are misconfigured.

Checking Inventory Availability

Inventory checks involve taking each cart item’s SKU and calculating the total quantity of that SKU in the cart across all items, then sending a request to through InventoryProvider to determine whether there is sufficient inventory available to satisfy that quantity. If insufficient inventory remains, then a message is added to the cart item’s global config errors like with other validation messages and can be displayed to the user, already localized.

Note

When checking inventory availability for serialized inventory, make sure to provide the sku reference in the following format: MY_SKU?serializationValue=1234567890.

When adding to cart, the serialization value should be declared using a cart item attribute choice named "inventorySerializationValue". When this is done, the serialization value automatically gets appended to the cart item’s SKU as part of the inventory check & reservation requests.

CartItemMergingService

Overview

Service responsible for merging similar CartItems on adds and updates.

Default Implementation Details

DefaultCartItemMergingService provides for configuring different merging types in cases such as adding the same item to the cart multiple times. The default types are:

  • COMBINE: Items with the same configurations are combined into one line item. Basically, this means the quantity of an existing item is incremented if the same item is added again.

  • SEPARATE: Each add request results in a new line item even if the same item is already in the cart.

  • REJECT_OR_IGNORE: The same item cannot be added to the cart more than once.

    • By default for single item add requests, this merging type will result in an RejectedItemMergeException if the same item is already in the cart. The caller can handle as desired.

    • For bulk add requests, no exception is thrown, the item is simply ignored.

    • To change the default behavior, override DefaultCartItemMergingService#handleRejectedMerges

This service also makes calls to CatalogProvider to retrieve the merging types of each product since that information is not stored on the cart.

Configuration

Use broadleaf.cartoperation.service.mergingType to set the global behavior. This can be overridden for specific products with Product#mergingType, which takes the same values. It could be useful to have the global merging type be COMBINE because that works for most products in a catalog but to also override it for specific products such as those that are very large or require special fulfillment considerations.