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>&nbsp;</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>&nbsp;</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.
CommerceItemShippingInfoMap
bean property is a map of CommerceItemShippingInfo 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 param.

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 ATG 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.