Sunday 29 June 2014

Price Generation in ATG

ATG Commerce pricing services are based on below two complementary elements:
  1. Pricing engines.
  2. Pricing calculators.
1. Pricing engines.
  •     Retrieving any promotions that are available to site visitors.
  •     Determining which pricing calculators generate prices.
  •     Invoking the calculators in the correct order.
 2. Pricing calculators.
  •     Looking up the price.
  •     Using information they receive from the pricing engines, promotions, and the qualifier service to determine prices. 

Before pricing happens, the following steps take place:

1. On a scheduled basis, the pricing engines load global promotions (those defined as applying automatically to all customers). An engine builds its list by using its globalPromotionsQuery property to query the Promotions repository, searching for any promotion where the Automatically Give to All Customers (global) property is set to true.

2. At the start of the customer session, a PricingModelHolder instance is created. PricingModelHolder calls each pricing engine’s getPricingModels() method.

3. The pricing engine getPricingModels() method gets any promotions listed in the activePromotions property of the current customer’s profile and merges them with the global promotions list it previously created.

4. PricingModelHolder periodically updates both the global and active promotions.

The result is that PricingModelHolder has a merged list of global and active promotions for each pricing engine. When the customer performs an action that prompts a pricing operation, such as adding an item to their cart, the following steps are performed:

1. The business layer logic (such as a PriceItem servlet bean in a page) invokes a pricing engine.

2. The pricing operation invokes PricingTools which then gets the PricingModelHolder for that customer.

3. PricingTools gets the promotions from the PricingModelHolder and calls the pricing engine’s priceItems method, passing in the promotions as a list.

4. The pricing engine applies its configured precalculators in the order in which they appear in its preCalculators property. A precalculator modifies a price without using any associated promotions. Each type of engine calls its corresponding type of precalculator.

5. The pricing engine then takes the promotions list that was passed in and can again veto promotions from that list. The remaining promotions are sorted by priority and then evaluated.

For each available promotion, ATG Commerce does the following:
  • The pricing engine calls the appropriate helper method (findQualifyingItems, findQualifyingOrder, or findQualifyingShipping) in the Qualifier class to determine which items should be discounted. The pricing engine passes the current pricing context into the helper method’s input parameters.
  • The findQualifyingItems() method calls evaluateTarget(), which returns a Collection of QualfiedItem objects, representing CommerceItem objects. The findQualifyingOrder() and findQualifyingShipping() methods return a single MatchingObject.
  • The QualifiedItem and MatchingObject include discount information such as the PMDL discount structure. 
  • The QualifiedItem or MatchingObject information is returned to the pricing engine, which uses the discount information to determine which calculator to use.
  • The pricing engine calls the calculator and passes in the items to be discounted and the discount information.
  • The calculator marks items that have received a discount, which might not be eligible for further promotions.
  • The qualifier marks items that have already been used as qualifiers for the promotion. This prevents the qualifier items from being used again during the same price calculation.
  • The calculator applies the discount to the list of objects.

6. The pricing engine applies its configured PostCalculators, which make any necessary modifications to the price after discounts have been applied. Each pricing engine calls postcalculators of its own type.
7. The pricing engine returns an updated PriceInfo object.

Note : This process is repeated every time a price is requested. Price requests are resource-intensive, and should be performed only when necessary.


    Sunday 15 June 2014

    ATG 10.2 BCC transaction issue

    While setting up the CRS (ATG 10.2, MySQL and JBoss 5.1), I have faced few issues.Here I am sharing the solution of one of them.The execution of initial (first) deployement on BCC failed due to below exception.

    CONTAINER:atg.repository.RepositoryException; SOURCE:org.jboss.util.NestedSQLException: Could not enlist in transaction on entering meta-aware object!; - nested throwable: (javax.transaction.SystemException: java.lang.Throwable: Unabled to enlist resource, see the previous warnings. tx=TransactionImple < ac, BasicAction: 7f000001:c41a:5395f5cb:a16b status: ActionStatus.ABORT_ONLY >); - nested throwable: (org.jboss.resource.JBossResourceException: Could not enlist in transaction on entering meta-aware object!; - nested throwable: (javax.transaction.SystemException: java.lang.Throwable: Unabled to enlist resource, see the previous warnings. tx=TransactionImple < ac, BasicAction: 7f000001:c41a:5395f5cb:a16b status: ActionStatus.ABORT_ONLY >)) at atg.adapter.gsa.GSAItemDescriptor.getPersistentItem(GSAItemDescriptor.java:5549) at atg.adapter.gsa.GSAItemDescriptor.getOrWaitForPersistentItem(GSAItemDescriptor.java:5053) at atg.adapter.gsa.GSAItemDescriptor.getItem(GSAItemDescriptor.java:3275) at atg.adapter.gsa.GSARepository.getItem(GSARepository.java:353) at atg.deployment.repository.ReferenceItemGenerator.findReferenceItemInRepository(ReferenceItemGenerator.java:699) at ........................................

    The soltion to this issue is to update jboss connection datasource file (atg-ds.xml) for xa-datasource (replace local-tx-datasource with xa-datasource).Update the other elements of the file accordingly.

    Below is the sample connection detail.

    <xa-datasource>
    <jndi-name>ATGProductionDS</jndi-name>
    <xa-datasource-property name="URL">
                           jdbc:mysql://localhost:3306/Production
            </xa-datasource-property>
    <xa-datasource-class>
                           com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
            </xa-datasource-class>
    <xa-datasource-property name="User">CRS_Production</xa-datasource-property>
    <xa-datasource-property name="Password">CRS_Production</xa-datasource-property>
    <min-pool-size>5</min-pool-size>
            <!-- The maximum connections in a pool/sub-pool -->
           <max-pool-size>300</max-pool-size>
      <!-- To avoid deadlocks you need set this -->
      <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
    </xa-datasource>