Vista de caja negra de la arquitectura del motor de promociones

El motor de promociones es el núcleo del componente de la promoción. El motor de promociones está rodeado por tres conjuntos de API: las API de gestión de persistencia, las API de gestión de dependencia y las API de tiempo de ejecución.

El diagrama siguiente muestra el motor de promociones como una caja negra.

Motor de promoción como una caja negra

El bloque central del diagrama representa el motor de promociones. El motor de promociones está bien protegido por los tres conjuntos de API, tal como se ilustra en el diagrama.

El primer conjunto de APIs son las API de gestión de persistencia. Estas API definen las interacciones entre el motor de promociones y un sistema de almacenamiento persistente. Este almacenamiento persistente permite al motor de promociones almacenar objetos persistentes, tales como promociones, políticas de promoción, los resultados de aplicar promociones a un pedido y estadísticas.

El segundo conjunto de APIs es la capa de definiciones de dependencias. Esta capa define cómo se muestra HCL Commerce ante el motor de promociones, definiendo un conjunto de interfaces como las de pedidos, clientes, perfiles de cliente y entradas de catálogo. Define las dependencias de objeto que el motor de promociones tiene en HCL Commerce. HCL Commerce tiene un modelo de datos muy complejo. El motor de promociones no está interesado en todos los detalles del modelo de datos. Mediante la definición de la API de dependencias, el motor de promociones declara explícitamente cómo utiliza el modelo de datos de HCL Commerce, y se aísla de los cambios en el modelo de datos de HCL Commerce.

El tercer conjunto de APIs son las API de ejecución. Estas API realizan dos tareas. En primer lugar, proporcionan una API de inicialización del sistema. Actualmente, esta API la invoca HCL Commerce Server. Cuando WebSphere Commerce Server se inicializa, llama a este conjunto de APIs, pasando la información de configuración del motor de promociones, y da instrucciones al motor de promociones para que se inicialice. En segundo lugar, proporcionan una API de invocación mediante la cual el subsistema de pedidos de HCL Commerce llama al motor de promociones cuando prepara un pedido. Define los parámetros de entrada y de salida del método de llamada, así como cualquier caso de excepción y código de error posibles.

HCL Commerce está representado como el bloque exterior. Contiene el modelo de datos, la lógica de negocio y el mecanismo de gestión de persistencia de HCL Commerce. HCL Commerce proporciona el motor de promociones con servicios de gestión de persistencia utilizando la API de gestión de persistencia definida, e implementa la capa de dependencias que requiere el motor de promociones utilizando el modelo de datos de HCL Commerce.

Los detalles de las API se describen con más detalle en las secciones siguientes.

Integración de las API de ejecución y del subsistema de pedidos

El conjunto de las API de ejecución consta de dos llamadas. El primer método lleva a cabo la inicialización del sistema. Es muy poco probable que esta API necesite personalizarse alguna vez, por lo tanto, en esta sección se examinan los API de invocación. Las API de invocación del motor de promociones contienen un solo método en la interfaz PromotionEngine y un solo parámetro de entrada y salida, denominado PromotionArgument. La única excepción definida es PromotionRuntimeException, que es una excepción sin verificar.

La definición del método es la siguiente:


PromotionArgument invoke(
    String template,
    Long orderId,
      boolean discardPreviousResult,
      boolean saveCurrentResult,
      Hashtable NVP)
throws PromotionRuntimeException;

El primer parámetro de este método, llamado template, es de tipo serie. Esto define el nombre de la plantilla que se utiliza para invocar el motor. Las plantillas en la forma prescrita para llamar al motor de promociones. Una plantilla contiene una lista ordenada de promociones. Las plantillas se configuran en el archivo XML de configuración de promoción. Este archivo de configuración se examina más adelante en este documento. El fragmento XML siguiente muestra una configuración de plantilla típica. Los comentarios del fragmento XML explican la función de cada sección del fragmento.


<Template>
      <!-- A template has a key, comprised of a reference to the owning 
        store, and string name unique within the store. If the store reference 
        refers to the "NullEntity" store of the "root organization", this 
        template is considered a "wildcard" template. If the promotion engine 
        is called in a store for which no template with the given name can be 
        found. The promotion engine searches wildcard templates and attempts 
        to find a name match. If a match is found, this wildcard template is 
        used with all the references to "NullEntity" store replaced with 
        references to the store within which the promotion engine is called. 
        This includes all of the store references in the group key definition 
        in the template.
        -->

   <TemplateKey>
      <!--A template is identified by a key which is made up of a reference 
        to a store and a string identifier unique within the store. -->

      <StoreKey>
         <DN>o=root organization</DN>
         <Identifier>NullEntity</Identifier>
      </StoreKey>
         <!--This is the string identifier. Currently, the only template used 
           by HCL Commerce is named "All Promotions".
         -->
      <Name>All Promotions</Name>
   </TemplateKey>

      <!-- This section defines for the template, which of the following four 
        monetary values associated with an order and order items are present:
        
              Price
              Tax
              Shipping Charge
              Tax on Shipping Charge
             -->

     <MonetaryValuePresence>
            <Price>true</Price>
            <ShippingCharge>false</ShippingCharge>
            <Tax>false</Tax>
            <ShippingTax>false</ShippingTax>
      </MonetaryValuePresence>

          <!-- list of promotion groups will be given -->

        <PromotionGroupKey>
            <StoreKey>
               <DN>o=root organization</DN>
                 <Identifier>NullEntity</Identifier>
            </StoreKey>
            <GroupName>ProductLevelPromotion</GroupName>
         </PromotionGroupKey>
         <PromotionGroupKey>
            <StoreKey>
          <DN>o=root organization</DN>
          <Identifier>NullEntity</Identifier>
       </StoreKey>
       <GroupName>OrderLevelPromotion</GroupName>
     </PromotionGroupKey>
     <PromotionGroupKey>
        <StoreKey>
           <DN>o=root organization</DN>
           <Identifier>NullEntity</Identifier>
        </StoreKey>
        <GroupName>ShippingPromotion</GroupName>
     </PromotionGroupKey>
  </Template>

Actualmente, la única plantilla utilizada por HCL Commerce se llama "All Promotions". Contiene los grupos de promociones "ProductLevelPromotion", "OrderLevelPromotion" y "ShippingPromotion", en este orden. Cuando se llama a esta plantilla, el único valor monetario que está disponible para un pedido o un artículo de pedido es la información sobre el precio. Los impuestos, los costes de envío y los impuestos sobre el envío no se calculan cuando se llama al motor de promociones.

El segundo parámetro de este método, llamado orderId, es de tipo Long. Se trata de la clave primaria del pedido al que deben aplicarse todas las promociones.

Los parámetros tercero y cuarto de este método son de tipo booleano. El tercer parámetro se llama "discardPreviousResult". Es una directriz para el motor de promociones. Ordena al motor de promociones que elimine cualquier registro anterior sobre cómo se aplican las promociones al pedido actual, es decir, el pedido cuya clave primaria se especifica en la llamada. Cuando el tercer parámetro se establece en true, los resultados anteriores se eliminan. Cuando este valor se establece en false, los resultados anteriores se cargan en la memoria y la evaluación de promociones continúa a partir del punto en que se detuvo previamente, lo que permite realizar llamadas al motor de promociones con estado. (Debido a un problema de asignación de recursos, esta invocación con estado de la característica de motor de promociones no ha sido objeto de la misma comprobación exhaustiva que la invocación sin estado del motor de promociones. Se recomienda que utilice la invocación sin estado para cualquier posible personalización.) El cuarto parámetro, llamado saveCurrentResult, es otra directriz que indica al motor de promociones si los resultados actuales deben tener persistencia en la base de datos. Este parámetro se establece normalmente en true.

Este último parámetro está reservado para permitir cualquier posible personalización que requiera parámetros adicionales. Es del tipo Hashtable, lo que significa que es simplemente un portador de parejas nombre-valor. Hay algo a tener en cuenta, y es que CommandContext, un objeto de HCL Commerce común, se guarda en esta Hashtable con el nombre "cmdContext".

El motor de promociones genera una excepción PromotionRuntimeException si se encuentra con un error del que no puede recuperarse. Esto es algo que no ocurre normalmente. Los errores de usuario, como códigos de promoción entrados incorrectamente, no desencadenarán una excepción de este tipo. Esta excepción es una subclase de RuntimeException, que es una excepción sin verificar.

Los parámetros de entrada son simples. Por el contrario, el parámetro de salida del método es bastante complejo. Este parámetro de salida es PromotionArgument.

Nota: PromotionArgument también puede actuar de parámetro de entrada. Un método nuevo de la implementación predeterminada del motor de promociones acepta un parámetro PromotionArgument como entrada. Incluye todos los parámetros de entrada individuales además de información adicional.

El diagrama siguiente muestra la estructura de esta clase. Las signaturas detalladas de estas interfaces y clases pueden encontrarse en la información de la API de estas entidades.

aquí va una imagen

PromotionArguments devuelve una lista de PromotionErrorReport. Actualmente, sólo se devuelven como errores los problemas asociados al uso incorrecto de códigos de promoción y cupones, como códigos y cupones incorrectos o caducados. Las violaciones de las políticas de promoción hacen que las promociones, que sean aplicables al pedido actual, no se apliquen. Esta situación no se considera errónea. No se generará ningún PromotionErrorReport como resultado.

Además de los informes de error, PromotionArgument incluye una lista de PromotionExecutionRecords. Un PromotionExecutionRecord es la evidencia de que una promoción se aplica a un pedido una vez. Si una promoción se aplica a un pedido N veces, se devuelven N PromotionExecutionRecords. Cada PromotionExecutionRecord incluye una gran variedad de información.

En primer lugar, incluye una referencia a la promoción que se aplica al pedido actual. Incluye también un código de promoción correspondiente, si se entra y se utiliza uno para tener derecho a esta promoción.

Opcionalmente, mantiene una referencia a un Cupón si se canjea uno para esta promoción.

Lo más importante, un PromotionExecutionRecord devuelve un LineItemSet que contiene todos los artículos de pedido (o partes de los artículos de pedido, si la cantidad de un artículo de pedido es más de 1) que son targeted de esta promoción. Si un artículo de pedido se incluye como objetivo, eso significa que se utiliza para tener derecho a una promoción. Un artículo de pedido objetivo no obtiene necesariamente un descuento como resultado de aplicar la promoción. Los artículos de pedido a los que se les aplica realmente el descuento se denominan artículos de pedido affected.

Los artículos de pedido afectados son siempre un subconjunto de los artículos de pedido objetivo. PromotionExecutionRecord mantiene una lista de artículos de pedido afectados en forma de matriz de LineItemSet. Con cada LineItemSet de la matriz hay asociado un Ajuste correspondiente. El Ajuste captura los cambios realizados en los artículos de pedido del LineItemSet afectado como resultado de aplicar esta promoción. Existen tres maneras de asociar un Ajuste a un LineItemSet:

  • El Ajuste se aplica a cada unidad de artículos de LineItemSet. Por ejemplo, si un FixedAmountOffAdjustment ofrece un descuento de 5 y se asocia con el LineItemSet de este modo, a cada unidad de artículos de pedido de LineItemSet se le descontarán 5. Tenga en cuenta que 5 está asociado con cada unidad de artículos de pedido, no con cada artículo de pedido. Esto es significativo cuando un artículo de pedido contiene cantidades superiores a 1.
  • El Ajuste se aplica a todos los artículos de LineItemSet. Por ejemplo, si un FixedAmountOffAdjustment ofrece un descuento de 5 y se asocia con el LineItemSet de este modo, se aplicará un descuento total de 5 a cada artículo, independientemente del número de artículos que haya en el LineItemSet.
  • El Ajuste se aplica al pedido entero en su totalidad. En este caso, el LineItemSet en sí mismo es irrelevante. Esta es la única excepción en la que los artículos afectados (el pedido entero) pueden no ser un subconjunto de los artículos objetivo.

El Ajuste se define como una interfaz. A continuación se listan las diferentes implementaciones:

Actualmente, el subsistema de pedidos llama al motor de promociones a través de esta API. Los dos mandatos que llaman al motor de promociones son:

  1. PromotionEngineOrderCalculateCmdImpl
  2. com.ibm.commerce.order.calculation.PromotionEngineDiscountCalculationCodeCombineCmdImpl

Cuando se llama al motor de promociones, éste procesa todas las promociones para el pedido actual y devuelve un PromotionArgument. A continuación, el subsistema de pedidos se ocupa de interpretar los resultados (PromotionArgument) devueltos por el motor de promociones y de almacenar los resultados en las tablas de ajustes de pedido y artículo de pedido respectivas. Debido a limitaciones en el subsistema de pedidos, éste no da soporte a todos los Ajustes. La siguiente es una lista de los Ajustes soportados totalmente por el subsistema de pedidos:

  • FreePurchasableGiftAdjustment
  • FixedAmountOffAdjustment
  • FixedAmountOffPriceAdjustment
  • FixedAmountOffVolumeDiscountAdjustment
  • FixedCostAdjustment
  • FixedCostShippingAdjustment
  • PercentOffAdjustment
  • PercentOffPriceAdjustment
  • VoucherAdjustment
Nota: Para soportar VoucherAdjustment, un escucha se debe registrar en el motor de promociones para emitir cupones cuando finaliza una promoción. Este aspecto se aborda en el tema Sucesos y escuchas de las promociones.

Si se utiliza un tipo de Ajuste que no está soportado por el subsistema de pedidos, éste simplemente hará omiso del Ajuste devuelto por el motor de promociones. El creador de este nuevo tipo de ajuste será entonces el responsable de aplicar este ajuste cuando se finalice la promoción.

Modelo de dependencia y dependencias actuales

El segundo conjunto de APIs que permite aislar el motor de promociones del resto de HCL Commerce son las API de dependencias. Éstas describen todas las entidades externas de las que depende el motor de promociones (PromotionEngine). Actualmente, este conjunto de dependencias incluye:

  • Campaign
  • CatalogEntry
  • Categoría
  • Cliente
  • CustomerProfile
  • Orden
  • Artículo de pedido
  • Store

Todas estas entidades siguen el mismo patrón de implementación en el motor de promociones. Este patrón se ilustra en el diagrama siguiente, en el que se utiliza Order como ejemplo:

aquí va una imagen

Para cada una de estas entidades, hay definida una clave (OrderKey). Así es cómo se identifica externamente esta entidad. La dependencia se declara como una interfaz (Order). Hay definida una fábrica abstracta (OrderFactory). Esta fábrica busca y crea instancias de entidades externas. PromotionEngine es propietario de un ExternalEntityFactoryRegistry, donde está registrada la fábrica concreta (WCSOrderFactory). Durante la ejecución, el motor de promociones interactúa con la interfaz de dependencias (Order) y la fábrica abstracta (OrderFactory), que se implementan mediante WCSOrder y WCSOrderFactory.

El fragmento XML siguiente se utiliza para configurar ExternalEntityFactoryRegistry, que es parte de la configuración del motor de promociones. Puede que las líneas estén partidas por motivos de presentación:


<ExternalEntityFactoryRegistry 
          impl="com.ibm.commerce.marketing.promotion.dependency.ExternalEntityFactoryRegistry">
   <OrderFactory 
          impl="com.ibm.commerce.marketing.promotion.integration.dependency.WCSOrderFactory" />
   <OrderItemFactory 
          impl="com.ibm.commerce.marketing.promotion.integration.dependency.WCSOrderItemFactory" />
   <CustomerFactory 
          impl="com.ibm.commerce.marketing.promotion.integration.dependency.WCSCustomerFactory" />
   <CustomerProfileFactory 
          impl="com.ibm.commerce.marketing.promotion.integration.dependency.WCSCustomerProfileFactory" />
   <CatalogEntryFactory 
          impl="com.ibm.commerce.marketing.promotion.integration.dependency.WCSCatalogEntryFactory" />
   <StoreFactory 
          impl="com.ibm.commerce.marketing.promotion.integration.dependency.WCSStoreFactory" />
   <CampaignFactory 
          impl="com.ibm.commerce.marketing.promotion.integration.dependency.WCSCampaignFactory" />
</ExternalEntityFactoryRegistry>

Estas ocho entidades externas de las que depende el motor de promociones siguen el mismo patrón de implementación. Tenga en cuenta que, si deben especificase atributos adicionales de un pedido, puede ampliar las dos clases mostradas en verde en el diagrama para añadir el atributo y registrar la nueva fábrica concreta en ExternalEntityFactoryRegistry. Además, si el motor de promociones tiene que integrarse con un sistema que no sea HCL Commerce, se necesita un conjunto diferente de dependencias externas. En el caso de Order, deben implementarse dos clases nuevas para sustituir las dos clases de color verde del diagrama.

Persistencia

El último conjunto de APIs que cierra el cortafuegos que hay alrededor del motor de promociones es la API de gestión de persistencia. Es necesario que los objetos siguientes del motor de promociones tengan persistencia:

  • Promotion
  • PromotionGroup
  • PromotionPolicy
  • Coupon
  • PromotionArgument
  • Estadísticas de promoción
  • DynamicAttribute

La persistencia de estos objetos se gestiona de manera idéntica. El diagrama siguiente muestra cómo maneja su persistencia el motor de promociones, utilizando Promotion como ejemplo.

aquí va una imagen

El servicio de persistencia que el motor de promociones necesita se define como una interfaz (PromotionPersistenceManager). Luego, pueden proporcionarse implementaciones concretas. La implementación concreta se registra entonces en el PersistenceManagerRegistry propiedad del motor de promociones. Los detalles de todas estas clases e interfaces se pueden encontrar en la información de las API.

El servicio proporcionado por las API de gestión de persistencia incluye las operaciones C.R.U.D para objetos que necesitan persistencia. Este conjunto de APIs es la base de cualquier herramienta de creación de contenido para promociones, incluido HCL Commerce Accelerator.

El fragmento XML siguiente se utiliza para configurar el PersistenceManagerRegistry. Forma parte de la configuración del motor de promociones. Puede que las líneas estén partidas por motivos de presentación:


<PersistenceManagerRegistry 
          impl="com.ibm.commerce.marketing.promotion.persistence.PersistenceManagerRegistry">
   <PromotionPersistenceManager 
          impl="com.ibm.commerce.marketing.promotion.PromotionSessionBeanPersistenceManager">
      <InitialCacheSize>1024</InitialCacheSize>
      <MaxCacheSize>8192</MaxCacheSize>
   </PromotionPersistenceManager>
   <PromotionPolicyPersistenceManager 
          impl="com.ibm.commerce.marketing.promotion.policy.PromotionPolicySessionBeanPersistenceManager">
      <InitialCacheSize>32</InitialCacheSize>
      <MaxCacheSize>1024</MaxCacheSize>
   </PromotionPolicyPersistenceManager>
   <PromotionGroupPersistenceManager 
          impl="com.ibm.commerce.marketing.promotion.group.PromotionGroupSessionBeanPersistenceManager">
      <InitialCacheSize>32</InitialCacheSize>
      <MaxCacheSize>1024</MaxCacheSize>
   </PromotionGroupPersistenceManager>
   <DynamicAttributePersistenceManager 
          impl="com.ibm.commerce.marketing.promotion.dynattr.DynamicAttributeSessionBeanPersistenceManager>
      <InitialCacheSize>32</InitialCacheSize>
      <MaxCacheSize>1024</MaxCacheSize>
   </DynamicAttributePersistenceManager>
   <PromotionArgumentPersistenceManager 
          impl="com.ibm.commerce.marketing.promotion.runtime.PromotionArgumentSessionBeanPersistenceManager" />
   <CouponPersistenceManager 
          impl="com.ibm.commerce.marketing.promotion.coupon.CouponSessionBeanPersistenceManager" />
   <StatsPersistenceManager 
          impl="com.ibm.commerce.marketing.promotion.stats.StatsSessionBeanPersistenceManager" />
</PersistenceManagerRegistry>