Customers can publish gift lists so that other customers can search for them and view and purchase the items listed on them. (Wish lists are similar to gift lists, except they are private and can be seen only by their owners. They are not searchable.) In order to implement gift list searching and gift purchasing for the Pioneer Cycling Store, we used the GiftlistSearch form handler to search for gift lists, GiftListDroplet to add and remove gift lists from a profile, and GiftitemLookupDroplet to view and purchase gift items.

Searching for Gift Lists

The GiftlistSearch component is a configurable component used for gift list searching. For the Pioneer Cycling Store, we use the standard configuration to search for gift lists. The searching criteria used are: owner name, owner state, event name, and event type. The following configuration file, GiftlistSearch.properties, configures an instance of the atg.commerce.gifts.SearchFormHandler class.

/atg/commerce/gifts/GiftlistSearch.properties

$class=atg.commerce.gifts.SearchFormHandler
$scope=session

doNameSearch=true
nameSearchPropertyNames=owner.firstName,owner.lastName

doAdvancedSearch=true
advancedSearchPropertyNames=eventType,eventName,state

doPublishedSearch=true
publishedSearchPropertyNames=public,published

profileRepository^=/atg/userprofiling/ProfileTools.profileRepository
profileTools=/atg/userprofiling/ProfileTools
itemTypes=gift-list

The next code sample is from giftlist_search.jsp. It demonstrates how we used the GiftlistSearch component to find published gift lists. This file has been split into two parts to show what each section does. The first half of the code displays previously found (if any) gift lists that have been added to the customer profile.

The following code can be found <ATG2007.3dir>/PioneerCyclingJSP/j2ee-apps/pioneer/
web-app/en/catalog/giftlist_search.jsp
:

<%/*
Display the  giftlists that customer is shopping for.
*/%>

<dsp:droplet name="IsEmpty">
  <dsp:param bean="Profile.otherGiftlists" name="value"/>
  <dsp:oparam name="false">
  <b>You are shopping for these people</b><br>
  <hr size=0>
  <dsp:droplet name="/atg/dynamo/droplet/ForEach">
    <dsp:param bean="Profile.otherGiftlists" name="array"/>
    <dsp:oparam name="output">
         <p>
      <b><dsp:valueof param="element.owner.firstName"/>
      <dsp:valueof param="element.owner.middleName"/>
      <dsp:valueof param="element.owner.lastName"/></b></br>
      <dsp:valueof param="element.eventName"/>
      <dsp:valueof date="d-MMM-yyyy" param="element.eventDate"/><br>
      <b>Event Description</b><br>
      <dsp:valueof param="element.description"/><br>
      <b>Extra Information</b><br>
      <dsp:valueof param="element.instructions"/><br>
      > <dsp:a href="./giftlist_view.jsp"> <dsp:param name="giftlistId"
             param="element.id"/>View the items in this gift list</dsp:a>
      <br>
      > <dsp:a href="./giftlist_search.jsp">
           <dsp:param name="giftlistId" param="element.id"/>
           <dsp:param name="action" value="remove"/>
           Stop shopping for this person</dsp:a>
    </dsp:oparam>
  </dsp:droplet>
  <hr size=0>
</dsp:oparam>

<dsp:oparam name="true"></dsp:oparam>

</dsp:droplet>

When rendered, the page lists all previously found gift lists and provides customers with a form to perform additional searches.

The second half of giftlist_search.jsp as shown here does the searching. It takes input from the customer and, on submit, searches the repository for published gift lists that meet the criteria.

The following code can be found in <ATG2007.3dir>/PioneerCyclingJSP/j2ee-apps/pioneer/
web-app/en/catalog/giftlist_search.jsp
:

<dsp:droplet name="ForEach">
 <dsp:param bean="GiftlistSearch.searchResults" name="array"/>
 <dsp:oparam name="output">
  <dsp:a href="./giftlist_search.jsp">
      <dsp:param name="action" value="add"/>
      <dsp:param name="searching" value="false"/>
      <dsp:param name="giftlistId" param="element.id"/>
      <dsp:valueof param="element.owner.firstName"/>
      <dsp:valueof param="element.owner.middleName"/>
        <dsp:valueof param="element.owner.lastName"/>
   </dsp:a>
 <dsp:valueof param="element.eventName"/>
 <dsp:valueof param="element.eventDate"/>
 <br>
 </dsp:oparam>
</dsp:droplet>

</blockquote>

</dsp:oparam>
<dsp:oparam name="true">

    Your search found no giftlists <p>

</dsp:oparam>
</dsp:droplet>
</tr>
</table>

  </dsp:oparam>
</dsp:droplet>

<dsp:form action="giftlist_search.jsp">
<p>
<b>Find someone's gift list</b>
<hr size=0>
Name: <dsp:input bean="GiftlistSearch.searchInput" size="30" type="text"/>
<p>
Optional criteria that may make it easier to find the right list:
<p>

<dsp:droplet name="ForEach">
<%-- For each property specified in
 GiftlistSearch.advancedSearchPropertyNames, retrieve all possible
 property values. This allows the customer
 to pick one to search on for advanced searching. --%>
<dsp:param bean="GiftlistSearch.propertyValuesByType" name="array"/>
<dsp:oparam name="output">
<dsp:droplet name="Switch">
 <dsp:param name="value" param="key"/>
 <%-- One property that a product in the store can have is weight range.
  In this case, if the property is weight range, we want to put all
  possible choices in a pulldown menu. --%>
 <dsp:oparam name="eventType">
 Event Type
  <%-- property to store the customer's selection is propertyValues --%>
  <dsp:select bean="GiftlistSearch.propertyValues.eventType">
  <dsp:option value=""/>Any
  <dsp:setvalue paramvalue="element" param="outerelem"/>
  <dsp:droplet name="ForEach">
   <dsp:param name="array" param="outerelem"/>
   <dsp:oparam name="output">

   <dsp:getvalueof id="eventTypeName" param="element" idtype="java.lang.String">
    <dsp:option value="<%=eventTypeName%>"/>
   </dsp:getvalueof>

   <dsp:valueof param="element">UNDEFINED</dsp:valueof>
   </dsp:oparam>
  </dsp:droplet>
  </dsp:select><br>
 </dsp:oparam>

 <dsp:oparam name="eventName">
  <b>Event Name
  <%-- property to store the customer's selection is propertyValues --%>
  <dsp:input bean="GiftlistSearch.propertyValues.eventName" size="30"
             type="text" value=""/>
  <br>
 </dsp:oparam>
 <dsp:oparam name="state">
  <b>State
  <%-- property to store the customer's selection is propertyValues --%>
  <dsp:input type="text" size="30" bean="GiftlistSearch.propertyValues.state"
             value=""/> <br>
 </dsp:oparam>
 </dsp:droplet>
 </dsp:oparam>
 </dsp:droplet>
Viewing Someone Else’s Gift Lists

The View the items on this gift list link takes the customer to a giftlist_view.jsp page. For this feature, we used the GiftlistLookupDroplet to retrieve the gift list from the repository by Id. The following code sample shows how we used the component and displayed each item on the list and information about it.

The following code can be found in <ATG2007.3dir>/PioneerCyclingJSP/j2ee-apps/pioneer/
web-app/en/catalog/giftlist_view.jsp
:

<%/* check if parameter giftlistId has been passed into page. if
   it has, then call GiftlistDroplet to do something */ %>
<dsp:droplet name="IsEmpty">
<dsp:param name="value" param="giftlistId"/>
<dsp:oparam name="false">
 <dsp:droplet name="/atg/commerce/gifts/GiftlistLookupDroplet">
  <dsp:param name="id" param="giftlistId"/>
  <dsp:oparam name="output">
   <dsp:droplet name="IsEmpty">
    <dsp:oparam name="false">
    <dsp:setvalue paramvalue="element" param="giftlist"/>
    <span class=storebig>Gift List for
    <dsp:valueof param="giftlist.owner.firstName"/>
    <dsp:valueof param="giftlist.owner.middleName"/>
    <dsp:valueof param="giftlist.owner.lastName"/>
    </span>
    <br>
    <p>
    <blockquote>
    <b>Event name:</b><dsp:valueof param="giftlist.eventName"/>
    <br>
    <b>Event date:</b><dsp:valueof date="d-MMM-yyyy" param="giftlist.eventDate"/>
    <p>

    <table cellspacing=0 cellpadding=0 border=0>
      <tr valign=bottom>
        <td><b>Quantity<br>wanted</b></td>
        <td>&nbsp;</td>
       <td><b>Quantity<br>bought</b></td>
       <td>&nbsp;&nbsp;&nbsp;</td>
       <td><b>Product</b></td>
      </tr>
    <tr><td colspan=5><hr size=0></td></tr>
      <tr valign=top>
    <dsp:droplet name="/atg/dynamo/droplet/ForEach">
     <dsp:param name="array" param="giftlist.giftlistItems"/>
     <dsp:oparam name="output">
      <dsp:setvalue paramvalue="element" param="item"/>
      <dsp:droplet name="/atg/commerce/catalog/ProductLookup">
       <dsp:param name="elementName" value="product"/>
       <dsp:param name="id" param="item.productId"/>
       <dsp:oparam name="output">
       <td><dsp:valueof param="item.quantityDesired">quantity
                desired</dsp:valueof></td><td></td>
       <td><dsp:valueof param="item.quantityPurchased">quantity
                purchased</dsp:valueof></td><td></td>
       <td>

          <dsp:droplet name="/atg/dynamo/droplet/IsNull">
           <dsp:param name="value" param="product.template"/>
           <dsp:oparam name="true">
            <dsp:valueof param="product.displayName">ERROR:no product
                 name</dsp:valueof>
           </dsp:oparam>
           <dsp:oparam name="false">
            <dsp:getvalueof id="templateUrl" idtype="String"
                 param="product.template.url">
            <dsp:a page="<%=templateUrl%>">
             <dsp:param name="id" param="product.repositoryId"/>
             <dsp:param name="giftId" param="item.id"/>
             <dsp:param name="giftlistId" param="giftlistId"/>
             <dsp:param name="gift" value="true"/>
             <dsp:param name="navAction" value="jump"/>
             <dsp:valueof param="product.displayName">ERROR:no product
                  name</dsp:valueof>
            </dsp:a>
            </dsp:getvalueof>
           </dsp:oparam>
          </dsp:droplet>

       </td>
       </tr>
       </dsp:oparam>
      </dsp:droplet>
     </dsp:oparam>
     <dsp:oparam name="unset">
      Your giftlist is empty
     </dsp:oparam>
    </dsp:droplet>
      </tr>
    </table>
    <p>
    <b>Event description:</b><br>
    <dsp:valueof param="giftlist.description"/><br>
    <p>
    <b>Ship to:</b>
    <blockquote>
    </blockquote>
    <p>
    </span>
    <%
    /* Where are the gifts going to be sent to?
    This person may be different from the owner of the giftlist, so
    we need to display the shipping address person, city and state. */
    %>
    <dsp:valueof param="giftlist.shippingAddress.firstName"/>
    <dsp:valueof param="giftlist.shippingAddress.middleName"/>
    <dsp:valueof param="giftlist.shippingAddress.lastName"/><br>
    <dsp:valueof param="giftlist.shippingAddress.city"/>,
    <dsp:valueof param="giftlist.shippingAddress.state"/><br>
    </blockquote>
    <p>
    </dsp:oparam>
    <dsp:oparam name="true">
     Nothing to look at here.
    </dsp:oparam>
   </dsp:droplet>
  </dsp:oparam>
 </dsp:droplet>
</dsp:oparam>
</dsp:droplet>

The figure shows how the above code sample displays information about the event and items. For each item, it shows quantity wanted and quantity purchased to date. A link to that product page displays the product and an “add to cart” button.

Address privacy

Security is always an important factor. When customers register a gift list on the Pioneer Cycling store, they select one of their stored shipping addresses for the list. This way, friends know where to send their gifts. All addresses in ATG Consumer Commerce have an owner ID. All pages where the address may appear (gift list details, order summary) verify the owner ID before displaying complete address information. The current profile ID is compared to the owner ID of the address. If they are not equal, only the city and state are displayed and the street address is hidden. Because this code is at the page level, individual sites can select a security level as required. The following code sample demonstrates how we used the switch servlet bean on the owner id property of an address to show limited information.

The following code can be found in <ATG2007.3dir>/PioneerCyclingJSP/j2ee-apps/pioneer/
web-app/en/Checkout/full/co_confirm.jsp
:

<!-- If address owner id = profile id, then display street address -->
  <dsp:droplet name="Switch">
   <dsp:param name="value" param="ShippingGroup.shippingAddress.ownerId"/>

   <!-- If this user "owns" this address, pass in private=false: -->
   <dsp:getvalueof id="nameval3" bean="Profile.id" idtype="java.lang.String">
<dsp:oparam name="<%=nameval3%>">
    <dsp:getvalueof id="pval0" param="ShippingGroup.shippingAddress">
    <dsp:include page="../../user/DisplayAddress.jsp" flush="true">
    <dsp:param name="address" value="<%=pval0%>"/>
    <dsp:param name="private" value="false"/></dsp:include></dsp:getvalueof>
   </dsp:oparam>
</dsp:getvalueof>

   <!-- Else pass in private=true: -->
   <dsp:oparam name="default">
    <dsp:getvalueof id="pval0" param="ShippingGroup.shippingAddress">
    <dsp:include page="../../user/DisplayAddress.jsp" flush="true">
    <dsp:param name="address" value="<%=pval0%>"/>
    <dsp:param name="private" value="true"/></dsp:include></dsp:getvalueof>
   </dsp:oparam>
  </dsp:droplet>

en\user\DisplayAddress.jsp:

<dsp:importbean bean="/atg/dynamo/droplet/IsEmpty"/>
<dsp:importbean bean="/atg/dynamo/droplet/Switch"/>

<DECLAREPARAM NAME="address"
       CLASS="java.lang.Object"
       DESCRIPTION="A ContactInfo Repository Item to display">

<DECLAREPARAM NAME="private"
       CLASS="boolean"
       DESCRIPTION="If true, we will hide the details of the address.">


<dsp:valueof param="address.firstName"/>
<dsp:valueof param="address.middleName"/>
<dsp:valueof param="address.lastName"/>
<br>
<dsp:droplet name="Switch">
 <dsp:param name="value" param="private"/>
 <dsp:oparam name="true">
 </dsp:oparam>
 <dsp:oparam name="default">
  <dsp:valueof param="address.address1"/><br>
  <dsp:droplet name="IsEmpty">
   <dsp:param name="value" param="address.address2"/>
   <dsp:oparam name="false">
    <dsp:valueof param="address.address2"/><br>
   </dsp:oparam>
  </dsp:droplet>
 </dsp:oparam>
</dsp:droplet>
<dsp:valueof param="address.city"/>,
<dsp:valueof param="address.state"/>
<dsp:valueof param="address.postalCode"/>
<br>
<dsp:valueof param="address.country"/>
Purchasing Items from Gift Lists

Each page that shows a specific gift list has links to each product on the list that bring the customer to the corresponding product pages. Then, on each product page, the customer has the ability to add that gift item to a shopping cart. To do this, we used the addGiftItemToOrder in the ShoppingCartModifier component to add the gift to the customer’s shopping cart. Special handling instructions are created for a gift in a shopping cart. See the section on Extending the Purchase Process for Gift Lists in the Configuring Merchandising Services chapter of the ATG Commerce Programming Guide for a description of the purchase process. Customers can either continue shopping or proceed to checkout after they add gifts to their shopping carts.

The following sample is from en\catalog\GetItForGiftListBox.jsp:

<%/*
This fragment is placed on a product template. It allows a customer
to purchase something off someone else's gift list. It assumes that
param:product, param:giftlistId, and param:giftId are passed.
*/%>

<dsp:importbean bean="/atg/commerce/order/ShoppingCartModifier"/>
<dsp:importbean bean="/atg/commerce/catalog/SKULookup"/>

<dsp:droplet name="/atg/commerce/gifts/GiftlistLookupDroplet">
 <dsp:param name="id" param="giftlistId"/>
 <dsp:param name="elementName" value="giftlist"/>

 <dsp:oparam name="output">
 <table cellpadding=0 cellspacing=0 border=0>
     <tr>
      <td class=box-top-store>Get this gift for <dsp:valueof
          param="giftlist.owner.firstName">someone</dsp:valueof></td>
     </tr>

     <tr>
      <td class=box>

  <dsp:getvalueof id="form33" bean="/OriginatingRequest.requestURI"
       idtype="java.lang.String">
<dsp:form action="<%=form33%>" method="post">
  <input name="id" type="hidden" value='<dsp:valueof
         param="Product.repositoryId"/>'>
  <input type="hidden" name="itemType" value="Product">
  <input name="itemId" type="hidden" value='<dsp:valueof
         param="Product.repositoryId"/>'>
  <dsp:input bean="ShoppingCartModifier.addGiftItemToOrderSuccessURL"
       type="hidden" value="../checkout/cart.jsp"/>
  <dsp:input bean="ShoppingCartModifier.productId"
       paramvalue="Product.repositoryId" type="hidden"/>
  <dsp:input bean="ShoppingCartModifier.giftlistId" paramvalue="giftlist.id"
       type="hidden"/>
  <dsp:droplet name="/atg/commerce/gifts/GiftitemLookupDroplet">
  <dsp:param name="id" param="giftId"/>
  <dsp:param name="elementName" value="giftitem"/>
  <dsp:oparam name="output">
    <dsp:input bean="ShoppingCartModifier.giftlistItemId" paramvalue="giftitem.id"
         type="hidden"/>
     <dsp:input bean="ShoppingCartModifier.catalogRefIds"
          paramvalue="giftitem.catalogRefId" type="hidden"/>

     <dsp:valueof param="giftlist.owner.firstName">firstname</dsp:valueof> wants
     <dsp:valueof param="giftitem.quantityDesired">?</dsp:valueof>
   <dsp:droplet name="SKULookup">
    <dsp:param name="id" param="giftitem.catalogRefId"/>
    <dsp:param name="elementName" value="skuItem"/>
    <dsp:oparam name="output">
      <dsp:valueof param="skuItem.displayName">sku</dsp:valueof><br>
    </dsp:oparam>
   </dsp:droplet>
     and so far people have bought
     <dsp:valueof param="giftitem.quantityPurchased">?</dsp:valueof>.
     <p>

  </dsp:oparam>
</dsp:droplet>

<%/* URL to go to if user's session expires while he is filling out this form */%>
<dsp:input bean="ShoppingCartModifier.sessionExpirationURL" type="hidden"
     value="../../common/SessionExpired.jsp"/>

Buy <dsp:input bean="ShoppingCartModifier.quantity" size="4" type="text"
         value="1"/>
<dsp:input bean="ShoppingCartModifier.addGiftItemToOrder" type="submit" value="Add
     to Cart"/>
</dsp:form></dsp:getvalueof>

 </dsp:oparam>
</dsp:droplet>

This screenshot shows the product page for an item on the gift list and the option to purchase one for the customer:

Checkout with Gifts

During checkout, a customer may edit the shipping instructions for the gift. By default, the item ships to the address in the gift list; however, the purchaser may ship the gift to a different address. Once the order is processed and item shipped, the gift list is updated to display the quantity purchased for that item.

 
loading table of contents...