Friday, June 21, 2013

Configuring a New Fulfiller : ATG


A new fulfiller must be configured within Nucleus before it can be used by the fulfillment system. This section uses the example of configuring CustomFulfiller , the fulfiller created in the Creating a New Fulfiller section.

Use the ATG Control Center to edit the Configuration component located in atg/commerce/fulfillment/.

Change the property fulfillerPortNameMap to include the name of this new fulfiller.

Configure the port on which messages will be sent to this fulfiller. This is the port on which the OrderFulfiller component will send JMS messages for this fulfiller.

For example, add the following to Configuration.properties:

fulfillerPortNameMap+=\
   CustomFulfiller CustomFulFillerPort 

You will also need to define which types of shipping groups can be handled by your fulfiller.OrderFulfiller uses this information to verify that a shipping group can be fulfilled by its fulfiller.

For example, add the following to Configuration.properties:

fulfillerShippingGroupMap+=\
   CustomFulfiller =mypackage.MyShippingGroup

In this example, the fulfiller being added is called CustomFulfiller   The component using an instance of HardgoodFulfiller should make the name property of the HardgoodFulfiller CustomFulfiller 

For example, add the following to CustomFulfiller .properties:

fulfillerName=CustomFulfiller 

In addition, add the following properties to CustomFulfiller .properties:

orderManager^=Configuration.orderManager
orderFulfillmentTools^=Configuration.orderFulfillmentTools
messageSourceName=CustomFulfiller 
modifyNotificationPort=ModifyNotificationPort
shippingGroupStates=/atg/commerce/states/ShippingGroupStates
shipItemRelationshipStates=
        /atg/commerce/states/ShipItemRelationshipStates

Configure the CustomFulFillerPort in the dynamoMessagingSystem.xml file so that the OrderFulfiller component can send out the FulfillOrderFragment messages on this port.

For example, add the following dynamoMessagingSystem.xml for OrderFulfiller:

<message-filter>
      <nucleus-name>
        /atg/commerce/fulfillment/OrderFulfiller
      </nucleus-name>
       . . .
      <output-port>
        <port-name>
          CustomFulFillerPort 
        </port-name>
        <output-destination>
          <provider-name>
            sqldms
          </provider-name>
          <destination-name>
            sqldms:/Fulfillment/MyOwnGoods
          </destination-name>
          <destination-type>
            Topic
          </destination-type>
        </output-destination>
      </output-port>
       . . .
</message-filter>


Configure the CustomFulfiller  component to send messages on the modifyNotificationPort and listen for messages on the sqldms:/Fulfillment/MyOwnGoods topic. These topics are described above.

<message-filter>
      <nucleus-name>
           /myPackage/CustomFulfiller 
      </nucleus-name>
      <output-port>
        <port-name>
          ModifyNotificationPort
        </port-name>
        <output-destination>
          <provider-name>
            sqldms
          </provider-name>
          <destination-name>
            sqldms:/Fulfillment/ModifyOrderNotification
          </destination-name>
          <destination-type>
            Topic
          </destination-type>
        </output-destination>
      </output-port>
</message-filter>

<message-sink>
   <nucleus-name>
     /myPackage/CustomFulfiller 
   </nucleus-name>
   <input-port>
     <port-name>
       DEFAULT
     </port-name>

     <input-destination>
         <provider-name>
            sqldms
         </provider-name>
         <destination-name>
            sqldms:/Fulfillment/MyOwnGoods
         </destination-name>
         <destination-type>
            Topic
         </destination-type>
       </input-destination>
    </input-port>
</message-sink>

For more information, see the Dynamo Message System chapter of the ATG Programming Guide.

Set the MessageSourceName property of the CustomFulfiller  to “MyOrderFulfiller” or another value that indicates who sent a message. This allows the component to ignore messages that it sent itself.

Add another value to the fulfiller property of the SKU in the product catalog.

(Defined in /atg/commerce/catalog/productCatalog.xml) 

This should match the name of the fulfiller used to map to a port in OrderFulfillmentTools.fulfillerPortNameMap.

<item-descriptor name="sku" display-name="SKU"
     sub-type-property="type"
     display-property="displayName"
  . . .
  <property name="fulfiller" data-type="enumerated"
       column-name="fulfiller" queryable="false">
    <attribute name="useCodeForValue" value="false"/>
    <option value="HardgoodFulfiller" code="0"/>
    <option value="SoftgoodFulfiller" code="1"/>
    <option value="CustomFulfiller" code="2"/>
   </property>
   . . .
</item-descriptor>

The modificationHandler property can be modified to point to another component that extends atg.commerce.fulfillment.ModificationHandler to handle with different forms of modifications received by the fulfiller. The ModificationHandler class provides a simple framework for changing the handling of ModifyOrder and ModifyOrderNotifications. It is not necessary to use a separate ModificationHandler. In the example above, handleModifyOrderNotification was implemented directly within the fulfiller class CustomFulfiller 


------------------------------------------------------------------------------------------------------------.

Creating a New Fulfiller in ATG Commerce



You can create a new fulfiller if your site requires fulfillment functionality different from that of the HardgoodFulfiller or ElectronicFulfiller that ship with ATG Commerce. For example, you could create a new fulfiller if your customers can purchase a research report. Instead of allocating this report from inventory and shipping it to the customer via UPS or Federal Express, you send them the report as an attachment via e-mail. There is no need to check inventory since the report is automatically in stock. Shipment can be done immediately since your newly created fulfiller can interface directly with an e-mail system. This section will describe how to implement and configure this new simpler fulfiller. In this example, the new fulfiller is called CustomFulfiller.

JMS messages connect the new fulfiller and the rest of ATG Commerce. Specifically, fulfillment of a shipping group begins with a FulfillOrderFragment message. To receive these messages, the new fulfiller must implement atg.dms.patchbay.MessageSink.

In addition to receiving the FulfillOrderFragment messages, CustomFulfiller must send out messages to inform the rest of ATG Commerce about changes made to each order. To send these messages, CustomFulfiller must implement atg.dms.patchbay.MessageSource. There is a class in atg.commerce.messaging that provides most of the functionality CustomFulfiller will need to send and receive messages. This class is called SourceSinkTemplate. It implements both MessageSource and MessageSink. CustomFulfiller will be defined as follow:

package myPackage;
import atg.commerce.fulfillment.*;
import atg.commerce.messaging.*;

public class CustomFulfiller extends SourceSinkTemplate
The only method in SourceSinkTemplate that CustomFulfiller needs to overwrite is receiveMessage.

public void receiveMessage (String pPortName, Message pMessage)
      throws JMSException
{

The Patch Bay system calls this method when a message is sent to CustomFulfiller   For more information, see the Dynamo Message System chapter in the ATG Programming Guide. At this time, the only message CustomFulfiller listens for is FulfillOrderFragment. The receiveMessage method can check the type of the object in the message. Only the interested code will be listed here, error checking will be assumed.

if(pMessage.getJMSType().equals(FulfillOrderFragment.TYPE))
     handlFulfillOrderFragment(pMessage);
} // end of receiveMessage


The handleFulfillOrderFragment method retrieves the order from the message and the list of shipping groups that need to be fulfilled. For this example, the necessary error checking will be listed here.

Retrieve the FulfillOrderFragmentCommerceMessage from the incoming message:

public void handleFulfillOrderFragment(ObjectMessage pMessage)
{
      FulfillOrderFragment fragment =
            (FulfillOrderFragment) pMessage.getObject();

Retrieve the order and the shipping groups IDs:

Order order = fragment.getOrder();
String[] shippingGroupIds = fragment.getShippingGroupIds();

Call a new method called processShippingGroup for each shipping group in the message.

for(int i=0; i<shippingGroupIds.length; i++) {
      ShippingGroup sg =
            order.getShippingGroup(shippingGroupIds[i]);
      processShippingGroup(order, shippingGroup);
}

One of the responsibilities of CustomFulfiller is to notify the rest of ATG Commerce what changes were made to the order included in this FulfillOrderFragment. To do this, CustomFulfiller needs to remember each modification made. Therefore, inside handleFulfillOrderFragment, declare a new List that will contain Modification objects. These objects are added to the list as changes are made. This list will need to be included in any method calls. The above code now looks like this:

List modifications = new ArrayList();
for(int i=0; i<shippingGroupIds.length; i++) {
      ShippingGroup sg =
            order.getShippingGroup(shippingGroupIds[i]);
      processShippingGroup(order, shippingGroup,
                            modifications);
}

After processing is complete, CustomFulfiller saves the order and include the modifications in a message. This is handled by a method in the OrderFulfillmentTools:

OrderManager orderManager = getOrderManager();
OrderFulfillmentTools tools = getOrderFulfillmentTools();

orderManager.updateOrder(order);
tools.sendModifyOrderNotification(order.getId(), // order
   modificationList, // modifications
   null,             // ModifyOrder
   this,             // MessageSource
   getModifyOrderNotificationPort(),  // port
   null);            // original message
}  // end of handleFulfillOrderFragment

See the ATG API Reference for a detailed description of the OrderFulfillmentToolssendModifyOrderNotification method.

CustomFulfiller depends on a few properties being set to properly function. It will need an OrderManager, OrderFulfillmentTools, and a ModifyNotificationPort. This port is explained in the Configuring a New Fulfiller section.

The only method that has not been discussed is processShippingGroup. The following example is a simple example of the functions of processShippingGroup in order processing. The most important function is the manipulation of the object states. There are two more properties necessary for the fulfiller: ShippingGroupStates and ShipItemrRelationshipStates.

public void processShippingGroup(Order pOrder,
                ShippingGroup pShippingGroup,
                List pModificationList)
{
   ShippingGroupStates sgStates = getShippingGroupStates();
   ShipItemRelationshipStates sirStates =
     getShipItemRelationshipStates();
   OrderFulfillmentTools tools =
     getOrderFulfillmentTools();

. . . get each item relationship in the shipping group

. . . for each item

  . . . send the report via e-mail using the orders
       profile
     // set the state to DELIVERED


     tools.setItemRelationshipState(shipItemRel,
        sirStates.getStateValue(sirStates.DELIVERED),


        "Report has been e-mailed to customer",
        pModificationList);
. . . end for loop

// the shipping groups is finished

  tools.setShippingGroupState(pShippingGroup,
     sgStates.getStateValue(sgStates.NO_PENDING_ACTION),
     "This shipping group has finished shipping",
     pModificationList);
}


The methods in OrderFulfillmentTools create the appropriate modifications, which are sent in a ModifyOrderNotification message by handleFulfillOrderFragment. The new fulfiller is now ready to be configured into ATG Commerce.

It is possible that the e-mail cannot be sent because of some error. For example, if a message is sent out because the shipping group cannot be shipped and the message contains an invalid e-mail address. One possibility for dealing with this error is to set the ShippingGroup to PENDING_MERCHANT_ACTION. If you implement your fulfiller to do this, then the Customer Service Representative must correct the order and tell the fulfillment system to reprocess that shipping group with a ShippingGroupUpdate Modification sent within a ModifyOrderNotification message.

To facilitate this, MyOwnFulfiller.receiveMessage should be configured to listen for ModifyOrderNotification messages and call handleModifyOrderNotification if one of these messages is received. That method can then call processShippingGroup for each shipping group and send a new ModifyOrderNotification with all modifications that were made.

A new fulfiller must be configured within Nucleus before it can be used by the fulfillment system. See the Configuring a New Fulfiller section for more information.


------------------------------------------------------------------------------------------------------------

Adding Credit Card Types to ATG Commerce


This post describes how to extend ATG Commerce and a payment system integration to use the additional credit card types that the payment system might accept.

By default, ATG Commerce considers only common credit cards valid. These cards include Visa, MasterCard, etc. Many payment systems handle many other credit and debit cards, such as Switch/Solo. Many of these other cards have more validation parameters than the standard cards. If your commerce site needs to accept these cards, you can extend ATG Commerce to handle these card types.

The following sections describe the three parts to extending ATG Commerce to include new credit card types:


1. Extending the ATG Commerce CreditCard Class

2. Extending the ATG Commerce CreditCardInfo Class

3. Extending the Payment System Integration



Extending the ATG Commerce CreditCard Class


The following steps describe how to extend the CreditCard class and modify ATG Commerce to use the new class. For general information on extending a class and modifying the ATG Commerce purchase process, see the Extending the Purchase Process section of this chapter.

Create a subclass of atg.commerce.order.CreditCard and include any new properties you need for the credit card type. Add get/set methods for each of these properties. The get and set methods need to use super.getPropertyValue() and super.setPropertyValue(), so that the underlying repository item is updated correctly.

For example, the following code sample creates a property for the issue number of the credit card:

//------------------------------------------------------
   // property:IssueNumber
//------------------------------------------------------
   public void setIssueNumber(String pIssueNumber) {
     setPropertyValue("issueNumber",
             (pIssueNumber == null ? pIssueNumber :
              StringUtils.removeWhiteSpace(pIssueNumber)));
   }

   /**
    * The issue number of this credit card
    * @beaninfo description: The issue number of this credit card
    **/
   public String getIssueNumber() {
     return (String) getPropertyValue("issueNumber");
   }

Add columns to the dcspp_credit_card table to store your new properties for the CreditCard subclass.

Extend orderrepository.xml to add the new properties in your CreditCard subclass to the existing creditCard item descriptor.

Modify /atg/commerce/order/OrderTools to make ATG Commerce use your new CreditCard subclass instead of the default class. For example:

beanNameToItemDescriptorMap+=\
   my.class.dir.myCreditCard=creditCard

paymentTypeClassMap+=\
   creditCard=my.class.dir.myCreditCard

Modify /atg/commerce/payment/PaymentManger.paymentGroupToChainNameMap to contain a pointer to your new class:

paymentGroupToChainNameMap+=\
my.class.dir.myCreditCard=creditCardProcessorChain

Edit the following properties of /atg/commerce/payment/CreditCardTools to include appropriate values for your new CreditCard:

* cardCodesMap

* cardLengthsMap

* cardPrefixesMap

* cardTypesMap



Extending the ATG Commerce CreditCardInfo Class



The following steps describe how to extend the CreditCardInfo class to accommodate the new credit card type.

Create a subclass of atg.payment.creditcard.GenericCreditCardInfo, with any necessary new properties. Refer to the payment system’s documentation for information on what properties it needs to process the new credit card type.

Modify /atg/commerce/payment/processor/CreateCreditCardInfo.creditCardInfoClass to point to the new subclass.

Create a new class that extends atg.commerce.payment.processor.ProcCreateCreditCardInfo. In this class, extend the addDataToCreditCardInfo method to call the superclass, followed by code that adds your new properties (added in step 1) to the CreditCardInfo object.

Modify the class of CreditCreditCardInfo.properties to point to your new subclass.



Extending the Payment System Integration



The final part of the process of adding a new credit card type is to extend the credit card processor for your payment system to use your new card type’s properties in its validation mechanisms. The payment system integration will have an implementation of atg.payment.creditcard.CreditCardProcessor.

In addition, the $class line in the properties file for the credit card processor must be changed to use your new subclass.



------------------------------------------------------------------------------------------------------------

Popular Posts