Users may decide to ship the items in their order to multiple addresses by clicking the Ship to multiple addresses link to checkout/ship_to_multiple.jsp
.
Users are presented with dropdown lists of their available shipping addresses. They simply select the desired address and the appropriate quantity for each line item, and click the Save button.
The atg/commerce/order/purchase/ShippingGroupFormHandler
component is used to keep track of the user’s selections. It maintains a list of associations between the various line items and how they are apportioned among shipping addresses, and allows the user to ship one set of items to one address and another set of items to another address. This component also accommodates shipping different quantities of the same item to different addresses.
First, the ShippingGroupDroplet
is initialized. The page takes an initialization parameter called init
that specifies whether the old ShippingGroupMapContainer
and CommerceItemShippingInfoContainer
should be cleared and reinitialized. This parameter is set to true
the first time the page is accessed. As the user modifies the information and the page is refreshed, the parameter is then set to false
to preserve the user’s changes.
Once initialized, the ShippingGroupMapContainer
contains the user’s ShippingGroups
, and the CommerceItemShippingInfoContainer
contains one CommerceItemShippingInfo
object per line item in the order. The following JSP from ship_to_multiple.jsp
ensures this initialization:
<dsp:droplet name="ShippingGroupDroplet">
<dsp:param name="clearShippingGroups" param="init"/>
<dsp:param name="initShippingGroups" param="init"/>
<dsp:param name="shippingGroupTypes" value="hardgoodShippingGroup"/>
You can have multiple shipping types by including multiple, comma-delimited entries in the shippingGroupTypes
value, such as value="hardgoodShippingGroup,electronicShippingGroup"
.
The user is presented with a form to specify a shipping address for each item in the order; the default address is selected automatically. Any changes made by the user essentially modify the CommerceItemShippingInfo
objects for each CommerceItem
object.
A CommerceItemShippingInfo
object holds the information that relates a ShippingGroup
in the ShippingGroupMapContainer
to a CommerceItem
by amount. If a CommerceItem
is going to be associated with more than one ShippingGroup
, then a CommerceItemShippingInfo
object must describe each of these associations. The CommerceItemShippingInfoContainer
maintains these associations structurally as a list of CommerceItemShippingInfo
objects keyed by the CommerceItem
.
We created a form by iterating over the CommerceItems
in the order. For each CommerceItem
, we iterate over its list of CommerceItemShippingInfo
objects. Initially each CommerceItemShippingInfo
object refers to a CommerceItem
, its quantity, and the ShippingGroup
specified by the DefaultShippingGroupName
of the ShippingGroupMapContainer
.
The form permits the user to update the SplitQuantity
and SplitShippingGroupName
property values of these CommerceItemShippingInfo
objects, and to submit these by calling the ShippingGroupFormHandler.splitShippingInfos
. Thus, CommerceItems
can be associated with additional or different ShippingGroups
than those provided by the ShippingGroupDroplet
initialization.
Here is the JSP from checkout/ship_to_multiple.jsp
that creates this form:
<%-- For each CommerceItem in the Order, we obtain a List of CommerceItemShippingInfo objects. Each CommerceItemShippingInfo object associates the CommerceItem to a particular ShippingGroup. --%> <dsp:droplet name="ForEach"> <dsp:param name="array" param="order.commerceItems"/> <dsp:oparam name="output"> <dsp:setvalue paramvalue="element" param="commerceItem"/> <dsp:setvalue bean="ShippingGroupFormHandler.listId" paramvalue="commerceItem.id"/> <dsp:droplet name="ForEach"> <dsp:param bean="ShippingGroupFormHandler.currentList" name="array"/> <dsp:oparam name="output"> <dsp:setvalue paramvalue="element" param="cisiItem"/> <dsp:form action="ship_to_multiple.jsp" method="post"> <tr valign=top> <td><nobr><dsp:valueof param= "commerceItem.auxiliaryData.catalogRef.manufacturer_part_number" /></nobr></td> <td></td> <td><dsp:a href="../catalog/product.jsp?navAction=jump"> <dsp:param name="id" param="commerceItem.auxiliaryData.productId"/> <dsp:valueof param= "commerceItem.auxiliaryData.catalogRef.displayName"/></dsp:a></td> <td></td> <td align=right><dsp:valueof param="element.quantity"/></td> <td> </td> <td> <%-- These form elements permit the user to assign ShippingGroups by name and for a specific quantity to a CommerceItem. --%> <dsp:input bean= "ShippingGroupFormHandler.currentList[param:index].splitQuantity" paramvalue="element.quantity" size="4" type="text"/></td> <td> </td> <td> <dsp:select bean= "ShippingGroupFormHandler.currentList[param:index]. splitShippingGroupName"> <dsp:droplet name="ForEach"> <dsp:param name="array" param="shippingGroups"/> <dsp:oparam name="output"> <dsp:droplet name="Switch"> <dsp:param name="value" param="key"/> <dsp:getvalueof id="SGName" idtype="String" param="cisiItem.shippingGroupName"> <dsp:getvalueof id="keyname" idtype="String" param="key"> <dsp:oparam name="<%=SGName%>"> <dsp:option selected="<%=true%>" value= "<%=keyname%>"/><dsp:valueof param="key"/> </dsp:oparam> <dsp:oparam name="default"> <dsp:option selected="<%=false%>" value= "<%=keyname%>"/><dsp:valueof param="key"/> </dsp:oparam> </dsp:getvalueof> </dsp:getvalueof> </dsp:droplet> <%-- equivalent code to switch droplet using core:case. Both of these work correctly. <dsp:getvalueof id="keyname" idtype="String" param="key"> <dsp:getvalueof id="SGName" idtype="String" param="cisiItem.shippingGroupName"> <core:switch value="<%=keyname%>"> <core:case value="<%=SGName %>"> <dsp:option selected="<%=true%>" value= "<%=keyname%>"/><dsp:valueof param="key"/> </core:case> <core:defaultCase> <dsp:option selected="<%=false%>" value= "<%=keyname%>"/><dsp:valueof param="key"/> </core:defaultCase> </core:switch> </dsp:getvalueof> </dsp:getvalueof> --%> </dsp:oparam> </dsp:droplet> </dsp:select> </td> <td></td> <td> <%--Split the CommerceItemShippingInfos and redirect right back here with init=false. --%> <dsp:input bean="ShippingGroupFormHandler.splitShippingInfosSuccessURL" type="hidden" value="ship_to_multiple.jsp?init=false"/> <dsp:input bean="ShippingGroupFormHandler.ListId" paramvalue= "commerceItem.id" priority="<%=(int) 9%>" type="hidden"/> <dsp:input bean="ShippingGroupFormHandler.splitShippingInfos" type= "submit" value=" Save "/> </td> </tr> </dsp:form> </dsp:oparam> </dsp:droplet> </dsp:oparam> </dsp:droplet>
We use a complex set of form elements here. The ShippingGroupDroplet.CommerceItemShippingInfoContainer.
bean property is a map of
CommerceItemShippingInfoMapCommerceItemShippingInfo
Lists
.
The value of the request parameter commerceItem.id
is the dynamic key used to obtain the CommerceItemShippingInfo
List
that corresponds to the current CommerceItem
in the outer ForEach
iteration. In order to obtain a reference to a particular CommerceItemShippingInfo
list, we set the ShippingGroupFormHandler.listId
property with the list’s key. The list is then exposed via the ShippingGroupFormHandler.currentList
property. We then iterate over the list and expose the splitQuantity
and splitShippingGroupName
properties of each item, as referenced in a list by the index
parameter.
When the user is satisfied with the ShippingGroup
to CommerceItem
associations, he or she clicks the Continue button to proceed with the purchase process. This invokes the ShippingGroupFormHandler.applyShippingGroups
handler. The handler collects the information in each CommerceItemShippingInfo
object and adds the appropriate ShippingGroups
to the order, along with their necessary relationships to each CommerceItem
. For more information on the ShippingGroupFormHandler
, see the Core Commerce Programming Guide. The JSP to accomplish this is as follows:
<%-- Invoke the applyShippingGroups handler and redirect to shipping_method.jsp upon success. --%> <dsp:form action="ship_to_multiple.jsp" method="post"> <dsp:input bean="ShippingGroupFormHandler.applyShippingGroupsSuccessURL" type="hidden" value="shipping_method.jsp"/> <dsp:input bean="ShippingGroupFormHandler.applyShippingGroups" type="submit" value="Continue"/> </dsp:form>
The user is then redirected to checkout/shipping_method.jsp
, where he or she may select a shipping method for each ShippingGroup
.