The CartModifierFormHandler
is used to add items to and remove items from an Order
, modify the quantity of items in the Order
, and prepare the Order
for the checkout process.
CartModifierFormHandler
is an instance of class atg.commerce.order.purchase.CartModifierFormHandler
; it is located in Nucleus at /atg/commerce/order/purchase/CartModifierFormHandler
.
Many of the methods in CartModifierFormHandler
call OrderManager.updateOrder()
to save the Order
in its present state to the Order Repository. For information on OrderManager.updateOrder()
and the updateOrder
pipeline that it executes, see the Updating an Order with the OrderManager subsection of Saving Orders in this section.
Note that users can also make changes to their orders through other purchase process form handlers that do not reprice orders, such as the form handlers that create and manage shipping groups. In these situations, where the user can change the current Order
in ways that affect its price, and where the form handler used to process those changes does not reprice the Order
, you should use the RepriceOrderDroplet
servlet bean to reprice the Order
before displaying its price to the user. For more information on RepriceOrderDroplet
, see Repricing Orders section of the Commerce Guide to Setting Up a Store.
For detailed information on the CartModifierFormHandler
, refer to the ATG Platform API Reference.
The following sections describe the important methods in CartModifierFormHandler
. As can be seen from the method descriptions that follow, the handleAddXXX
and handleRemoveXXX
methods of CartModifierFormHandler
automatically reprice the Order
whenever the user makes changes to it.
However, you should note that users can also make changes to their orders through other purchase process form handlers that do not reprice orders, such as the form handlers that create and manage shipping groups. In these situations, where the user can change the current Order
in ways that affect its price, and where the form handler used to process those changes does not reprice the Order
, you should use the RepriceOrderDroplet
servlet bean to reprice the Order
before displaying its price to the user. For more information on RepriceOrderDroplet
, see Repricing Orders section of the Commerce Guide to Setting Up a Store.
getQuantity
Retrieves the quantities for the given items. This method looks up the request parameters to obtain the quantity of the item using getParameterValues()
.
getCatalogKey
Retrieves a string that identifies the catalog to use when obtaining a catalogRef
and productRef
for the creation of a CommerceItem
. The string is determined by the user’s locale, which is obtained from the Request
object. Consequently, the key is the user’s locale and the value is the corresponding repository to use (for example, en_US=ProductCatalog, fr_FR=FrenchCatalog
). /atg/commerce/catalog/CatalogTools
maintains the key-to-catalog mapping.
getShippingGroupCommerceItemRelationships
Retrieves the list of ShippingGroupCommerceItemRelationships
within the order.
getLocationId
Retrieves the locationId
property, if set. The locationId
property is used to track item location for cross-channel sales.
handleAddItemToOrder
Adds items to an order by calling addItemToOrder()
, which actually adds the items to the Order
. It then calls OrderManager.updateOrder()
.
See the addItemToOrder()
method for more information.
handleAddConfigurableItemToOrder
Adds configurable items to an order by calling preaddItemToOrder()
and then addConfigurableItemToOrder()
. After the item has been added, it calls postAddItemToOrder()
.
handleSetOrder
Saves an Order
. It calls modifyOrder()
to validate the user’s changes and modify the Order
. It then calls runProcessSetOrder()
, which executes the pipeline set in CartModifierFormHandler.setOrderChainId
. Finally, it calls OrderManager.updateOrder()
.
See the modifyOrder()
and runProcessSetOrder()
methods for more information.
handleSetOrderByRelationshipId
Saves an Order
. It calls modifyOrderByRelationshipId()
to validate the user’s changes and modify the Order
. It then calls runProcessSetOrder()
, which executes the pipeline set in CartModifierFormHandler.setOrderChainId
. Finally, it calls OrderManager.updateOrder()
.
See the modifyOrderByRelationshipId()
and runProcessSetOrder()
methods for more information.
handleMoveToPurchaseInfo
Saves an Order
. Unlike handleSetOrder()
and handleSetOrderByRelationshipId()
, it also verifies that the Order
is ready for checkout.
The handle method calls modifyOrder()
to validate the user’s changes and modify the Order
. It then calls runProcessMoveToPurchaseInfo()
, which executes the pipeline set in CartModifierFormHandler.moveToPurchaseInfoChainId
. Finally, it calls OrderManager.updateOrder()
.
See the modifyOrder()
and runProcessMoveToPurchaseInfo()
methods for more information.
handleMoveToPurchaseInfoByRelId
Saves an Order
. Unlike handleSetOrder()
and handleSetOrderByRelationshipId()
, it also verifies that the Order
is ready for checkout.
The handle method calls modifyOrderByRelationshipId()
to validate the user’s changes and modify the Order
. It then calls runProcessMoveToPurchaseInfo()
, which executes the pipeline set in CartModifierFormHandler.moveToPurchaseInfoChainId
. Finally, it calls OrderManager.updateOrder()
.
See the modifyOrderByRelationshipId()
and runProcessMoveToPurchaseInfo()
methods for more information.
addItemToOrder
Invoked by handleAddItemToOrder()
. The method calls mergeItemInputForAdd()
. If all input values are valid, the method then calls doAddItemToOrder()
.
See the mergeItemInputForAdd()
and doAddItemToOrder()
methods for more information.
addConfigurableItemToOrder
Invoked by the handleaddConfigurableItemToOrder()
. This methods adds one or more commerce items to the order. The list of items comes from either the catalogRefIds
array and the productId
, or from the item’s array.
mergeItemInputForAdd
Invoked by addItemToOrder()
to unify the way input values are made available to doAddItemToOrder()
and to validate input values.
The method first calls CartModifierFormHandler.getItems()
. If the returned value is null
, the method constructs an items
array whose size matches the size of the return value from CartModifierFormHandler.getCatalogRefIds()
. The method copies the values from getCatalogRefIds()
into the items
array elements. Then the method copies the values returned by the following CartModifierFormHandler.getXXX
methods into the items
array elements: quantity
, productId
or productIds
, value
, commerceItemType
, giftlistId
, and giftlistItemId
.
If the initial CartModifierFormHandler.getItems()
call retrieves a non-null value, the method copies the value returned by CartModifierFormHandler.getCommerceItemType()
to every items
array element whose commerceItemType
subproperty was null
. The method also calls CartModifierFormHandler.mergeValueDictionaries()
to combine the Dictionary returned by CartModifierFormHandler.getValueDictionary()
with each items
array element’s Dictionary.
doAddItemToOrder
Invoked by addItemToOrder()
. The method retrieves the list of items to add by calling CartModifierFormHandler.getItems()
, and calls CartModifierFormHandler.getCatalogKey()
to determine which catalog to use. Then, for each item to add to the Order
, the method uses the PurchaseProcessHelper
class to do the following:
Creates a
CommerceItem
using thecommerceItemType
,catalogRefId
,productId
andquantity
found in the current array element fromgetItems()
.Adds the created
CommerceItem
to the order. Note that the “new” item may represent an increase in the quantity of an existing item if the item added is already in the order.Copies custom values from the current item’s
value
Dictionary to the newCommerceItem
.Calls the
PurchaseProcessHelper.getShippingGroupForItem()
method to get a shipping group of the appropriate type. The type can be determined in one of three ways.Passed in to
PurchaseProcessHelper
from theCartModifierFormHandler.getItems()[ ].shippingGroupType
. The passed-in type is used along with the item’s gift information (if any) to determine the correct shipping group to which the item should be added.If no
locationId
is set, use the first shipping group of the passed-in type (if that information is available) or the first shipping group on the order, regardless of the item type. If this is the desired behavior (perhaps you only sell goods with one shipping group type, and the default is always the correct type), set theaddItemToDefaultShippingGroup
property of the/atg/commerce/order/purchase/PurchaseProcessHelper
component totrue
. This property is set totrue
by default.If
locationId
is set, either find a shipping group of typeInStorePickupShippingGroup
or, if no such shipping group exists, create the shipping group. Add the item to theInStorePickupShippingGroup
.PurchaseProcessHelper
can determine the correct group from the item type (based on the SKU’sfulfiller
property value) and gift information. To use this behavior, set theaddItemToDefaultShippingGroup
property of the/atg/commerce/order/purchase/PurchaseProcessHelper
component tofalse
.
Calls
PurchaseProcessHelper.addItemToShippingGroup()
, which callsCommerceItemManager.addItemQuantityToShippingGroup()
which in turn takes the given quantity of theCommerceItem
and the givenShippingGroup
and creates aShippingGroupCommerceItemRelationship
of typeSHIPPINGQUANTITY
.For information on the
SHIPPINGQUANTITY
type ofShippingGroupCommerceItemRelationship
, see Relationship Types in the Using Relationship Objects section of the Working With Purchase Process Objects chapter.Calls
createConfigurableSubitems()
, which is an empty method that can be overridden as needed by sites that use configurable commerce items.Calls
processGiftAddition()
, which checks if the item that was added to the order is a gift (that is, the item’s inputgiftlistId
orgiftlistItemId
property is non-null
). If the item is a gift,processGiftAddition()
callsGiftListManager.addGiftToOrder()
to perform additional gift list processing.
After the above steps have been taken for all the new items, addItemToOrder()
calls runProcessRepriceOrder()
, which reprices the Order
by executing the pipeline set in CartModifierFormHandler.repriceOrderChainId
. Then, for each new item addItemToOrder()
calls runProcessAddItemToOrder()
, which executes the pipeline set in CartModifierFormHandler.addItemToOrderChainId
. Finally, the method fires a scenario event of type ItemAddedToOrder
for each new item.
See the runProcessRepriceOrder()
and runProcessAddItemToOrder()
methods for more information.
modifyOrder
Invoked by handleSetOrder()
and handleMoveToPurchaseInfo()
.
The modifyOrder
method modifies the Order
based on the changes made in the request. It iterates over each CommerceItem
in the Order
. For each CommerceItem
, it retrieves the current quantity by calling getQuantity()
and passing in the catalogRefId
(SKU ID) of the item.
Next, the method checks for the validation of the catalogRefId
in the removalCatalogRefIds
list. The modifyOrder
method creates a local variable removeLineItems
map, which is passed to the prepareLineItemsForRemoval
method. The prepareLineItemsForRemovalmethod
populates the map with the IDs and quantities and returns the array of removal IDs. The modifyOrder
method uses this variable to adjust the quantities. The quantity is calculated by subtracting the quantity corresponding to the catalogRefId
in the removalLineItems
map from the current quantity in the order.
modifyOrderByRelationshipId
Invoked by handleSetOrderByRelationshipId()
and handleMoveToPurchaseInfoByRelId()
.
The modifyOrderByRelationshipId()
method updates the Order
based on the changes made in the request and the existing ShippingGroupCommerceItemRelationships
in the Order
. It iterates over each ShippingGroupCommerceItemRelationship
in the Order
. For each ShippingCommerceItemRelationship
, it first checks to make sure the Relationship
is of type SHIPPINGQUANTITY. If it is not, then an exception is thrown. Then, the method retrieves the current quantity of the ShippingGroupCommerceItemRelationship
by calling getQuantity()
and passing in the ShippingGroupCommerceItemRelationship
ID.
Next, the method checks if the ID of the ShippingGroupCommerceItemRelationship
is in the removalRelationshipIds
list. The modifyOrderByRelationshipId
method creates a local variable removeLineItems
map, which is passed to the prepareLineItemsForRemoval
method. The prepareLineItemsForRemovalmethod
populates the map with the IDs and quantities and returns the array of removal IDs. The modifyOrderByRelationshipId
method uses this variable to adjust the quantities. The quantity is calculated by subtracting the quantity corresponding to the ShippingGroupCommerceItemRelIds
in the removalLineItems
map from the current ShippingGroupCommerceItemRelIds
quantity in the order.
If there are no references in the RemovalLineItems
map, then the quantity of the ShippingGroupCommerceItemRelationship
and the quantity of the associated CommerceItems
are adjusted appropriately.
For more information on the SHIPPINGQUANTITY
type of ShippingGroupCommerceItemRelationship
, see Relationship Types in the Using Relationship Objects section of the Working With Purchase Process Objects chapter.
handleRemoveItemFromOrder
Removes items from the Order
by CommerceItem
ID. This handle method calls deleteItems()
to delete the items from the Order
and then calls OrderManager.updateOrder()
.
See the deleteItems()
method for more information.
handleRemoveItemFromOrderByRelationshipId
Removes items from the Order
by ShippingGroupCommerceItemRelationship
ID. This handle method calls deleteItemsByRelationshipId()
to delete the items from the Order
and then calls OrderManager.updateOrder()
.
See the deleteItemsByRelationshipId()
method for more information.
deleteItems
Deletes all CommerceItems
whose IDs are in the removalCommerceIds
array. When adding an item to the removalCommerceIds
array, you can set the inputDelimiter
variable. This separator at the end of IDs indicates that the item is split across multiple lines on the UI, as used in Group Discount Promotions. By default, the separator is set to “#
”. Separators can be configured in CartModifierFormHandler
file.
Important: If you are using features that require splitting items across multiple lines within the UI, ensure that you are setting the item’s inputDelimiter
variable. If no inputDelimiter
variable is provided, the CartModifierFormHandler
assumes that all instances of the commerce item should be removed, instead of removing the item from a single line item.
First, the entries to the removalCommerceIds
are validated by the prepareLineItemsForRemoval()
to see if the CommerceItemId
is followed by a separator and a quantity. If the method identifies a separator followed by a quantity, it checks to see if the quantity matches the entire quantity of the item. If it does, the entry is kept in the removalCommerceIds
property. The deleteItems
method creates a local variable removeLineItems
map, which is passed to the prepareLineItemsForRemoval
method. The prepareLineItemsForRemovalmethod
populates the map with the IDs and quantities and returns the array of removal IDs. The deleteItems
method uses this variable to adjust the quantities. The quantity is calculated by subtracting the quantity corresponding to the catalogRefId
in the removalLineItems
map from the current quantity in the order.
The method also removes all associated ShippingGroupCommerceItemRelationships
and calls runProcessRepriceOrder()
, which reprices the Order
by executing the pipeline set in CartModifierFormHandler.repriceOrderChainId
. Finally, the method fires a scenario event of type ItemRemovedFromOrder
.
See the runProcessRepriceOrder()
method for more information.
deleteItemsByRelationshipId
This method deletes CommerceItems
from the Order
by ShippingGroupCommerceItemRelationship
ID. It iterates through the IDs in the removalShippingGroupCommerceItemRelIds
property.
When developing pages, the page developer must use a removal separator when the items are split up as per their shipping groups, and their membership within a group of group-discounted items.
This separator at the end of IDs indicates that the item is split across multiple lines on the UI, as used in Group Discount Promotions. By default, the separator is set to “#
”. Separators can be configured in CartModifierFormHandler
file.
Important: If you are using features that require splitting items across multiple lines within the UI, ensure that you are setting the item’s removalSeparator
variable. If no removalSeparator
variable is provided, the CartModifierFormHandler
assumes that all instances of the commerce item within a specific shipping group should be removed, instead of removing the item from a single line item.
First, the entries to the removalShippingGroupCommerceItemRelIds
are validated by the prepareLineItemsForRemoval()
to see if the RelationshipId
is followed by a separator and a quantity. If the method identifies a separator followed by a quantity, it checks to see if the quantity matches the entire quantity of the item. If it does, the entry is kept in the removalShippingGroupCommerceItemRelIds
property.
The deleteItemsByRelationshipId
method creates a local variable removeLineItems
map, which is passed to the prepareLineItemsForRemoval
method. The prepareLineItemsForRemovalmethod
populates the map with the IDs and quantities and returns the array of removal IDs. The deleteItemsByRelationshipId
method uses this variable to adjust the quantities. The quantity is calculated by subtracting the quantity corresponding to the ShippingGroupCommerceItemRelIds
in the removalLineItems
map from the current ShippingGroupCommerceItemRelIds
quantity in the order.
For each ID, it also ensures that the Relationship
type is of type SHIPPINGQUANTITY (logging an error if it is not), and then it removes the HandlingInstructions
associated with the ShippingGroup
. The method then calls runProcessRepriceOrder()
, which re-prices the Order
by executing the pipeline set in CartModifierFormHandler.repriceOrderChainId
. Finally, the method fires a scenario event of type ItemRemovedFromOrder
. (See the runProcessRepriceOrder()
method in this table for more information.)
runProcessAddItemToOrder
Invoked by the handleAddItemToOrder()
method. This method runs the pipeline set in CartModifierFormHandler.addItemToOrderChainId
. By default, this property is set to addItemToOrder
.
Note: By default, the addItemToOrder
pipeline is commented out of commercepipeline.xml
, the commerce pipeline configuration file. It is provided for extension purposes, should you need to include additional functionality, such as scenario events.
runProcessSetOrder
Invoked by handleSetOrder()
and handleSetOrderByRelationshipId()
. This method runs the pipeline set in CartModifierFormHandler.setOrderChainId
. By default, this property is set to setOrder
.
Note: By default, the setOrder
pipeline is commented out of commercepipeline.xml
, the commerce pipeline configuration file. It is provided for extension purposes, should you need to include additional functionality, such as scenario events.
runProcessRepriceOrder
Runs the pipeline to execute whenever the order needs to be repriced. The pipeline to run is set in CartModifierFormHandler.repriceOrderChainId
. By default, this property is set to repriceOrder
. By default, this method executes an ORDER_TOTAL pricing operation. (For more information about pricing operations, see the Repricing Shopping Carts section of the Commerce Guide to Setting Up a Store.)
runProcessMoveToPurchaseInfo
Invoked by handleMoveToPurchaseInfo()
and handleMoveToPurchaseInfoByRelId()
. This method runs the pipeline set in CartModifierFormHandler.moveToPurchaseInfoChainId
. By default, this property is set to moveToPurchaseInfo
.
The moveToPurchaseInfo
pipeline, in turn, executes the validateForCheckout
pipeline, which verifies that the Order
is ready for checkout. For more information on both pipelines, see Appendix E: Pipeline Chains.