Motorprise offers a special promotion to customers whose current order price is at least 25% greater than their average order price. We implemented a custom condition in the Scenarios module to handle this requirement, and we extended the expression grammar in the ATG Control Center’s scenario editor to provide a customized user interface for creating and editing these conditions.

The Adding Custom Events, Actions, and Conditions to Scenarios chapter in the ATG Personalization Programming Guide explains how to create custom conditions and expression grammars.

We implemented our custom condition with the class atg.projects.b2bstore.scenario.PercentageComparisonFilter, which extends the standard ExpressionFilter class from the Scenarios module.

PercentageComparisonFilter supports conditions of the type:

   testValue [is at least / is at most]
      percentage percent [greater than / less than / of] baseValue

where testValue and baseValue are numeric expressions and percentage is a placeholder for a literal percentage value.

Motorprise, for example, uses this condition class for conditions of the type “Order’s price is at least 25% greater than person’s average order price”. In this case, testValue is “order’s price”, baseValue is “person’s average order price”, and percentage is 25.

Our custom condition expects to receive five operands when invoked:

  • Operand 1 is the test value, and must be a numeric value or expression.

  • Operand 2 indicates whether the comparison type is “at least” or “at most.” A string constant represents each possible value for this operand.

  • Operand 3 is the literal percentage value in the condition, which must be a number.

  • Operand 4 indicates whether the condition looks for the test value to be some percentage greater than, some percentage less than, or some percentage of the base value. As with the comparison type, a string constant represents each possible value.

  • Operand 5 is the base value, which must also be a numeric value or expression.

We specified the number and types of the operands when we registered our custom condition in scenarioManager.xml:

<condition-registry>
  <condition>
    <condition-name>orderPricePercentComparison</condition-name>
    <filter-class>atg.projects.b2bstore.scenario.
      PercentageComparisonFilter</filter-class>
    <resource-bundle>atg.projects.b2bstore.scenario.UserResources
    </resource-bundle>
    <display-name-resource>orderPricePercentComparison.displayName
    </display-name-resource>
    <description-resource>orderPricePercentComparison.description
    </description-resource>

<!--
    The action-parameter tags specify positional parameters that will
    be passed to the filter class's initialize() method.
-->

    <action-parameter>
      <action-parameter-name>
        testValue
      </action-parameter-name>
      <display-name-resource>
        orderPricePercentComparison.testValue.displayName
      </display-name-resource>
      <action-parameter-class>
        java.lang.Number
      </action-parameter-class>
      <required>
        true
      </required>
      <description-resource>
        orderPricePercentComparison.testValue.description
      </description-resource>
    </action-parameter>

    <action-parameter>
      <action-parameter-name>
        comparisonType
      </action-parameter-name>
      <display-name-resource>
        orderPricePercentComparison.comparisonType.displayName
      </display-name-resource>
      <action-parameter-class>
        java.lang.String
      </action-parameter-class>
      <required>
        true
      </required>
      <description-resource>
        orderPricePercentComparison.comparisonType.description
      </description-resource>
    </action-parameter>

    <action-parameter>
      <action-parameter-name>
        percentage
      </action-parameter-name>
      <display-name-resource>
        orderPricePercentComparison.percentage.displayName
      </display-name-resource>
      <action-parameter-class>
        java.lang.Integer
      </action-parameter-class>
      <required>
        true
      </required>
      <description-resource>
        orderPricePercentComparison.percentage.description
      </description-resource>
    </action-parameter>

    <action-parameter>
      <action-parameter-name>
        percentageType
      </action-parameter-name>
      <display-name-resource>
        orderPricePercentComparison.percentageType.displayName
      </display-name-resource>
      <action-parameter-class>
        java.lang.String
      </action-parameter-class>
      <required>
        true
      </required>
      <description-resource>
        orderPricePercentComparison.percentageType.description
      </description-resource>
    </action-parameter>

    <action-parameter>
      <action-parameter-name>
        baseValue
      </action-parameter-name>
      <display-name-resource>
        orderPricePercentComparison.baseValue.displayName
      </display-name-resource>
      <action-parameter-class>
        java.lang.Number
      </action-parameter-class>
      <required>
        true
      </required>
      <description-resource>
        orderPricePercentComparison.baseValue.description
      </description-resource>
    </action-parameter>

  </condition>
</condition-registry>

We also created a custom grammar extension to control how the ATG Control Center scenario editor displays and edits instances of this condition. The expression grammar generally follows the pattern described in Extending the Expression Editor in the Adding Custom Events, Actions, and Conditions to Scenario chapter in the ATG Personalization Programming Guide, but with two features that require extra explanation.

First, instead of using the standard <sequence> tag to begin our condition grammar we used the DCS <required-order-sequence> tag, as follows:

  <required-order-sequence id="condition-orderPricePercentComparison">

Using this tag tells the scenario editor that our custom condition can only appear in a scenario segment that already contains a DCS order event.

Otherwise, there would be no way to evaluate an expression like “Order’s price” as part of the condition.

Second, we used the custom grammar to constrain the condition’s first operand (the test value) to one of four predefined values. Even though the PercentageComparisonFilter class accepts any numeric expression as the test value, we wanted to limit the business user to selecting one of the following values:

  • Order price

  • Order price before discounts

  • Order tax

  • Order shipping cost

We accomplished this by using a <choice> tag as the first operand, where each token within the choice represents one of the four possible values:

<choice>
  <token>
    <description>Order price</description>
    <xml-template>
      <event-property>
        <property-name>order</property-name>
        <property-name>priceInfo</property-name>
        <property-name>total</property-name>
      </event-property>
    </xml-template>
  </token>

  <token>
    <description>Order price before discounts</description>
    <xml-template>
      <event-property>
        <property-name>order</property-name>
        <property-name>priceInfo</property-name>
        <property-name>rawSubTotal</property-name>
      </event-property>
    </xml-template>
  </token>

  <token>
    <description>Order tax</description>
    <xml-template>
      <event-property>
        <property-name>order</property-name>
        <property-name>priceInfo</property-name>
        <property-name>tax</property-name>
      </event-property>
    </xml-template>
  </token>

  <token>
    <description>Order shipping cost</description>
    <xml-template>
      <event-property>
        <property-name>order</property-name>
        <property-name>priceInfo</property-name>
        <property-name>shipping</property-name>
      </event-property>
    </xml-template>
  </token>
</choice>

Each token contains the description that appears in the scenario editor and an XML template for the corresponding event property using SDL, the scenario definition language. Each event property definition specifies one property of a DCS order event. For example, the event property definition is the SDL form of the event’s “order.priceInfo.total” subproperty:

<event-property>
  <property-name>order</property-name>
  <property-name>priceInfo</property-name>
  <property-name>total</property-name>
</event-property>

Copyright © 1997, 2012 Oracle and/or its affiliates. All rights reserved.

Legal Notices