Ejemplo: Cómo añadir soporte para un tipo de promoción personalizado

Este escenario añade soporte para un tipo de promoción adicional.

  1. Defina un modelo XML nuevo para el tipo de promoción personalizada.
  2. Analice los atributos nuevos que necesita la promoción personalizada para poder completar una condición de compra incluida una bonificación. Si un cliente compra cualquier artículo de la categoría de regalo personalizado, se muestra un anuncio con una promoción que ofrece una vela perfumada (un código de artículo individual) por 5 dólares. Se trata de una promoción de nivel de categoría de coste fijo.
    La información que la condición de compra y la bonificación requieren se definen de este modo:
    1. ID de categoría (por ejemplo: name)
    2. La cantidad que sea necesaria para la categoría de esta compra.
    3. Producto promocionado (por ejemplo: código de artículo de la velas de fiestas)
    4. La cantidad exacta del producto en promoción (valor predeterminado 1)
    5. El coste fijo asignado al producto en promoción.
  3. Cree una interfaz Java que define todas las constantes del nuevo tipo de descuento y los atributos nuevos para la interfaz de usuario de promociones, incluidos los archivos JSP y los beans de datos. Para crear esta interfaz:
    1. Abra el entorno de desarrollo de HCL Commerce (Inicio > Programas > HCL CommerceEntorno de desarrollo)
    2. Vaya al proyecto WebSphereCommerceServerExtensionsLogic.
    3. Pulse el botón derecho del ratón sobre el proyecto, seleccione Nuevo y luego Paquete.
    4. En el Campo de nombre del diálogo Paquete Java nuevo, escriba com.myCompany.epromotion.logic, donde myCompany representa algún nombre de directorio de cliente. Los paquetes creados por IBM, que se incluyen en HCL Commerce, siguen un convenio de denominación que empieza por com.ibm...
    5. Pulse Finalizar para crear el paquete nuevo.
    6. Pulse el botón derecho del ratón sobre el nuevo paquete, seleccione Nuevo y luego Interfaz.
    7. En el campo Nombre, escriba ExtendedPromotionConstants
    8. Pulse Finalizar. El archivo se abrirá en el editor.
    9. Actualice el archivo para que coincida con el ejemplo siguiente:
      
      package com.myCompany.epromotion.logic; 
      
      public interface ExtendedPromotionConstants extends com.ibm.commerce.tools.epromotion.RLConstants {
           // The new promotion types below are used for the promotion factory to identify 
           // each new promotion object.
           // These new types have to be registered in the RLPromotion.xml in order to be picked up
           // by Promotion Component Configuration
      
              public static final String PROMOTION_CATEGORYLEVELPWP = "CategoryLevelPurchaseWithPurchase";
              public static final String PROMOTION_PRODUCTLEVELPWP = "ProductLevelPurchaseWithPurchase";
              public static final String PROMOTION_ITEMLEVELPWP = "ItemLevelPurchaseWithPurchase";
           // The attributes below are for CategoryLevelPurchaseWithPurchase UI element naming convention,
           // the name should be matching with the one in UI databean in order to allow Tools FrameWork Java
           // Script object to pick up.
           // These attributes could also be reused by other types if the promotion condition is similar.
           
              public static final String PROMOTION_REQUIREDITEMQTY = "rlRequiredItemQty";
              public static final String PROMOTION_PROMOTEDITEMQTY = "rlPromotedItemQty";
              public static final String PROMOTION_PROMOTEDPRODUCTID = "rlPromotedProductId";
              public static final String PROMOTION_FIXCOST = "rlFixCost";
      }    
      
    10. Guarde el archivo, pero no cierre el entorno de desarrollo.
  4. Cree un objeto Java que represente el tipo de promoción personalizado. Este objeto presenta la nueva condición de compra y la bonificación y debe manejar la entrada y salida XML. Este objeto implementa la interfaz creada en el paso 3. Para crear este objeto:
    1. Vaya al proyecto WebSphereCommerceServerExtensionsLogic.
    2. Vaya a la carpeta src.
    3. Pulse con el botón derecho del ratón sobre la carpeta src, seleccione Nuevo y luego Paquete.
    4. En el campo Nombre del diálogo Paquete Java nuevo escriba un nombre exclusivo. En este ejemplo, escriba com.myCompany.epromotion.implementations, donde myCompany representa un nombre de imagen personalizado.
    5. Pulse Finalizar para crear el paquete.
    6. Pulse el botón derecho del ratón sobre el paquete com.myCompany.epromotion.implementations, seleccione Nuevo y luego Clase.
    7. En el campo Nombre del diálogo Clase Java nueva, escriba CategoryLevelPurchaseWithPurchase.
    8. En el campo Superclase del diálogo Objeto Java nuevo, escriba com.ibm.commerce.tools.epromotion.RLCategoryLevelPromotion.
    9. Pulse Finalizar. El archivo se abrirá en el editor.
    10. Actualice el archivo para que coincida con el ejemplo siguiente:
      
      package com.myCompany.epromotion.implementations;
      
      /**
       * The puchase condition in this sample is based on the category, therefore, this
       * Class extends {@link RLCategoryLevelPromotion}.
       * 
       * 
       * This XML will be generated in the {@link #toSpecificXML} method.
       * Also, all the fields in this class should be able to populate based on this XML through
       * {@link #populatePromotionSpecificDataFrom(String)}
       */
      
      import java.util.*;
      import java.text.Collator;
      import com.ibm.commerce.ras.*;
      import com.ibm.commerce.tools.epromotion.*;
      import com.ibm.commerce.tools.epromotion.util.*;
      import com.ibm.commerce.exception.*;
      
      import javax.xml.parsers.*;
      import org.xml.sax.InputSource;
      import org.w3c.dom.*;
      
      public class CategoryLevelPurchaseWithPurchase
         extends com.ibm.commerce.tools.epromotion.RLCategoryLevelPromotion
         implements com.myCompany.epromotion.logic.ExtendedPromotionConstants {
      
         /**
          * Customization: Define all the promotion purchase condition and reward attributes.
          * 1. The methods to retrieve the required item identification is in the parent class.
          * @see RLCategoryLevelPromotion#setCatalogGroupIDs(Vector)
          * 2. Terminology: based on the sample promotion: giving B a discount if purchase a number of A
          * A is the required item.
          * B is the promoted item.
          * 3. In this class, A is a category entity, B is a product/item based on user input.
          * The customized JSP, needs to support both search functions to allow choose product/item.
          */
      
         // The quantity required for the purchased item in order to get discount on promoted item.
         private int requiredItemQty;
        
         // The quantity of promoted item this promotion rule will give for a fixed cost.
         // default is 1 (option): which means fixed cost for each promoted item.
         // 2 means fixed cost for every 2 items...
         private int promotedItemQty=1;
      
         // The catalog entry identification of the promoted item
         private String promotedProductId;
       
         // The fix cost for the promoted items,
         // This value should be a String representation of Decimal
         private String fixCost;
       
         /**
          * This default promotion constructor.
          * There is no need to customized this constructor unless you have your own attributes
          * for new promotions, which should be initialized during object creation.
          */
         public CategoryLevelPurchaseWithPurchase() {
            super();
         }
       
         /**
          * It should always return the toSpecificXML(), there is no need customize it.
          */
         public String generatePromotionSpecificRuleXML() {
            return toSpecificXML();
         }
       
         /**
          * This method should be customized according to the new promotion purchase condition.
          * This method should generate the portion of the promotion XML, which fully describes
          * the purchase condition and reward relationship.
          */
         public String toSpecificXML() {
            final String methodName = "toSpecificXML()";
            // XmlHelper provides some utility function for XML String generation.
            XmlHelper helper = new XmlHelper();
            StringBuffer buffer = new StringBuffer();
            buffer
               .append("<PurchaseCondition impl=\"com.ibm.commerce.marketing.promotion.condition.PurchaseCondition\">")
               .append("<Pattern impl=\"com.ibm.commerce.marketing.promotion.condition.Pattern\">")
               .append("<Constraint impl=\"com.ibm.commerce.marketing.promotion.condition.Constraint\">")
               .append("<WeightedRange impl=\"com.ibm.commerce.marketing.promotion.condition.WeightedRange\">")
               .append("<LowerBound>")
               .append(this.getRequiredItemQty())
               .append("</LowerBound>")
               .append("<UpperBound>")
               .append(this.getRequiredItemQty())
               .append("</UpperBound>")
               .append("<Weight>1</Weight>")
               .append("</WeightedRange>")
               .append("<FilterChain impl=\"com.ibm.commerce.marketing.promotion.condition.FilterChain\">")
               .append(this.getRequiredItemFilter())
               .append("</FilterChain>")
               .append("</Constraint>")
               .append("<Constraint impl=\"com.ibm.commerce.marketing.promotion.condition.Constraint\">")
               .append("<WeightedRange impl=\"com.ibm.commerce.marketing.promotion.condition.WeightedRange\">")
               .append("<LowerBound>")
               .append(this.getPromotedItemQty())
               .append("</LowerBound>")
               .append("<UpperBound>")
               .append(this.getPromotedItemQty())
               .append("</UpperBound>")
               .append("<Weight>1</Weight>")
               .append("</WeightedRange>")
               .append("<FilterChain impl=\"com.ibm.commerce.marketing.promotion.condition.FilterChain\">")
               .append(this.getPromotedItemFilter())
               .append("</FilterChain>")
               .append("</Constraint>")
               .append("</Pattern>")
               .append("<Distribution impl=\"com.ibm.commerce.marketing.promotion.reward.Distribution\">")
               .append("<Type>Volume</Type>")
               .append("<Base>Quantity</Base>")
               .append("<Currency/>")
               .append("<Range impl=\"com.ibm.commerce.marketing.promotion.reward.DistributionRange\">")
               .append("<UpperBound>-1</UpperBound>")
               .append("<LowerBound>1</LowerBound>")
               .append("<RewardChoice>")
               .append("<Reward impl=\"com.ibm.commerce.marketing.promotion.reward.DefaultReward\">")
               .append("<AdjustmentFunction impl=\"com.ibm.commerce.marketing.promotion.reward.AdjustmentFunction\">")
               .append("<FilterChain impl=\"com.ibm.commerce.marketing.promotion.condition.FilterChain\">")
               .append(this.getPromotedItemFilter())
               .append("</FilterChain>")
               .append("<Adjustment impl=\"com.ibm.commerce.marketing.promotion.reward.FixedCostAdjustment\">")
               .append("<FixedCost>")
               .append(this.getFixCost())
               .append("</FixedCost>")
               .append("<Currency>")
               .append(this.getCurrency())
               .append("</Currency>")
               .append("<AdjustmentType>IndividualAffectedItems</AdjustmentType>")
               .append("</Adjustment>")
               .append("</AdjustmentFunction>")
               .append("</Reward>")
               .append("</RewardChoice>")
               .append("</Range>")
               .append("<PatternFilter impl=\"com.ibm.commerce.marketing.promotion.condition.DummyPatternFilter\" />")
               .append("</Distribution>")
               .append("</PurchaseCondition>");
              
               return buffer.toString();
            }
          
            public void fromSpecificXML(String xml) {
               final String methodName = "fromSpecificXML()";
         
               EproUtil util = new EproUtil();
               Collator collator = Collator.getInstance();
               // Get the promoted item from reward 
               String tempPromotedSKU =
                  XmlHelper
                     .getElementTextValueInNode(
                        XmlHelper.getXMLDocument(xml),
                        "Reward",
                        "SKU")
                     .firstElement()
                     .toString();
               String tempPromotedDN =
                  XmlHelper
                     .getElementTextValueInNode(
                        XmlHelper.getXMLDocument(xml),
                        "Reward",
                        "DN")
                     .firstElement()
                     .toString();
               try {
                  promotedProductId =
                     util.getCatEntryId(tempPromotedSKU, tempPromotedDN);
               } catch (ECException e) {
                  ECTrace.trace(
                     ECTraceIdentifiers.COMPONENT_MERCHANDISING,
                     getClass().getName(),
                     methodName,
                     e.toString());
                  // exception is handled inside the util class 
               }
               // Get the promoted item cost from the reward adjustment
               fixCost =
                  XmlHelper
                     .getElementTextValueInNode(
                        XmlHelper.getXMLDocument(xml),
                        "Adjustment",
                        "FixedCost")
                     .firstElement()
                     .toString();
               this.setCurrency(
                  XmlHelper
                     .getElementTextValueInNode(
                        XmlHelper.getXMLDocument(xml),
                        "Adjustment",
                        "Currency")
                     .firstElement()
                     .toString());
       
            // Get information from Pattern -- Constraint Node List
            NodeList nodeList =
               XmlHelper.getXMLDocument(xml).getElementsByTagName("Constraint");
            int size = nodeList.getLength();
            for (int i = 0; i < size; i++) {
               if (nodeList.item(i).hasChildNodes()
                  && (nodeList.item(i).getNodeType() == Node.ELEMENT_NODE)) {
                  Element element = (Element) nodeList.item(i);
                  NodeList catentryKeys =
                     element.getElementsByTagName("IncludeCatEntryKey");
                  if (catentryKeys.getLength() > 0) {
                     // this is the promoted item filter since it is the SKU Filter in this sample XML.
                     promotedItemQty =
                        Integer.parseInt(
                           element
                              .getElementsByTagName("LowerBound")
                              .item(0)
                              .getFirstChild()
                              .getNodeValue());
                  } 
                  NodeList categoryKeys =
                     element.getElementsByTagName("IncludeCategory");
                  if (categoryKeys.getLength() > 0) {
                     // This is the required category filter since it is the category Filter in the sample XML.
                     // The section below populates the required item quantity from XML.
                     requiredItemQty =
                        Integer.parseInt(
                           element
                              .getElementsByTagName("LowerBound")
                              .item(0)
                              .getFirstChild()
                              .getNodeValue());
                     // The section below populates the catalog group IDs
                     NodeList names = element.getElementsByTagName("Name");
                     NodeList dns = element.getElementsByTagName("DN");
                     Vector cgpIdentifiers = new Vector();
                     Vector cgpIds = new Vector();
                     for (int j = 0; j < names.getLength(); j++) {
                        try {
                           String tempCatGrpId =
                              util.getCatGroupId(
                                 names
                                    .item(j)
                                    .getFirstChild()
                                    .getNodeValue(),
                                 dns.item(j).getFirstChild().getNodeValue());
                           if (tempCatGrpId != null
                              && (collator.compare(tempCatGrpId.trim(), "")
                                 != 0)) {
                              cgpIds.addElement(tempCatGrpId);
                              cgpIdentifiers.addElement(
                                 names
                                    .item(j)
                                    .getFirstChild()
                                    .getNodeValue());
                           } 
                        } catch (ECException e) {
                           ECTrace.trace(
                              ECTraceIdentifiers.COMPONENT_MERCHANDISING,
                              getClass().getName(),
                              methodName,
                              e.toString());
                        } 
                     }
                     this.setCatalogGroupIDs(cgpIds);
                     this.setCatgpIdentifiers(cgpIdentifiers);
                  }   
               }
            } 
         } 
       
         public void populatePromotionSpecificDataFrom(Map h)
            throws com.ibm.commerce.exception.ParameterNotFoundException {
            requiredItemQty =
               EproUtil.toInt(
                  EproUtil.doCheckParameterFound(h, PROMOTION_REQUIREDITEMQTY));
            promotedItemQty =
               EproUtil.toInt(
                  EproUtil.doCheckParameterFound(h, PROMOTION_PROMOTEDITEMQTY));
            promotedProductId =
               EproUtil
                  .doCheckParameterFound(h, PROMOTION_PROMOTEDPRODUCTID)
                  .toString();
            fixCost =
               EproUtil.doCheckParameterFound(h, PROMOTION_FIXCOST).toString();
         } 
      
         public void populatePromotionSpecificDataFrom(String s) {
            // This method always call fromSpecificXML(xml) internally.
            this.fromSpecificXML(s);
         }
      
         /**
          * Set the quantity required for the purchased item in order to get discount on promoted item.
          * @param newRequiredItemQty the required item quantity passed by user.
          */
         public void setRequiredItemQty(int newRequiredItemQty) {
            this.requiredItemQty = newRequiredItemQty;
         } 
      
         /**
          * Get the quantity required for the purchased item in order to get discount on promoted item.
          * @return requiredItemQty
          */
         public int getRequiredItemQty() {
           return this.requiredItemQty;
         }
         
         /**
          * Set the quantity of promoted item this promotion rule will give.
          * @param newPromotedItemQty
          */
         public void setPromotedItemQty(int newPromotedItemQty) {
            this.promotedItemQty = newPromotedItemQty;
         }
         
         /**
          * Get the quantity of promoted item this promotion rule will give.
          * @return promotedItemQty
          */
         public int getPromotedItemQty() {
            return this.promotedItemQty;
         }
        
         /**
          * Set the catalog entry identification of the promoted item.
          * @param newPromotedProductId
          */
         public void setPromotedProductId(String newPromotedProductId) {
            this.promotedProductId = newPromotedProductId;
         }
        
         /**
          * Get the catalog entry identification of the promoted item.
          * @return promotedProductId
          */
         public String getPromotedProductId() {
            return this.promotedProductId;
         }
      
         /**
          * Set the fix cost for the promoted item.
          * @param newFixCost
          */
         public void setFixCost(String newFixCost) {
            this.fixCost = newFixCost;
         }
        
         /**
          * Get the fix cost for the promoted item,
          * @return fixCost
          */
         public String getFixCost() {
           return this.fixCost;
         }
       
         /**
          * This method is generating the Filter XML object for the promoted item.
          * @return promotedItemFilter the XML String
          */
         protected String getPromotedItemFilter() {
            final String methodName = "getPromotedItemFilter()";
            XmlHelper helper = new XmlHelper();
            StringBuffer buffer = new StringBuffer();
            buffer
               .append("<Filter impl=\"com.ibm.commerce.marketing.promotion.condition.MultiSKUFilter\">")
               .append("<IncludeCatEntryKey>")
               .append("<CatalogEntryKey>");
            try {
               buffer.append(
                  helper.generateProductXMLStringByCatentryId(
                     "SKU",
                     "DN",
                     this.getPromotedProductId()));
            } catch (ECException e) {
               ECTrace.trace(
                  ECTraceIdentifiers.COMPONENT_MERCHANDISING,
                  getClass().getName(),
                  methodName,
                  "CatalogEntryKey Generation Error "
                  + this.getPromotedProductId()
                  + e.toString());
            }
            buffer.append(";</CatalogEntryKey>").append(
               "</IncludeCatEntryKey>").append(
               "</Filter>");
            return buffer.toString();
         }
         protected String getRequiredItemFilter() {
            final String methodName = "getRequiredItemFilter()";
            XmlHelper helper = new XmlHelper();
            StringBuffer buffer = new StringBuffer();
            // The parent class is actually getting the targetted category identification for this promotion.
            buffer.append(
               "<Filter impl=\"com.ibm.commerce.marketing.promotion.condition.CategoryFilter\">");
            for (int i = 0; i < this.getCatalogGroupIDs().size(); i++) {
               buffer.append("<IncludeCategory>").append("<CategoryKey>");
               try {
                  buffer.append(
                     helper.generateCategoryXMLStringByCatgroupId(
                        "Name",
                        "DN",
                        this.getCatalogGroupIDs().elementAt(i).toString()));
               } catch (ECException e) {
                  ECTrace.trace(
                     ECTraceIdentifiers.COMPONENT_MERCHANDISING,
                     getClass().getName(),
                     methodName,
                     "Category Key Generation Error "
                        + this.getCatalogGroupIDs().elementAt(i).toString()
                        + e.toString());
               }
               buffer.append("</CategoryKey>").append("</IncludeCategory>");
           }
           buffer.append("</Filter>");
           return buffer.toString();
         }
      }
      
    11. Guarde el archivo, pero no cierre el entorno de desarrollo.
  5. Amplíe RLProductDiscountDataBean de modo que dé soporte al nuevo tipo de promoción. Este nuevo bean de datos cumplimenta los atributos nuevos en las páginas de cuaderno y de resumen. Para actualizar este bean de datos:
    1. En el entorno de desarrollo de HCL Commerce, vaya al proyecto WebSphereCommerceServerExtensionsLogic.
    2. Pulse con el botón derecho del ratón sobre la carpeta src, seleccione Nuevo y luego Paquete.
    3. En el Campo de nombre del diálogo Paquete Java nuevo, escriba com.myCompany.epromotion.databeans, donde myCompany representa un nombre personalizado de directorio de cliente.
    4. Pulse el botón derecho del ratón sobre el nuevo paquete, seleccione Nuevo y luego Clase.
    5. En el campo Nombre, escriba ExtendedPromotionDataBean.
    6. En el campo superclase, escriba lo siguiente: com.ibm.commerce.tools.epromotion.databeans.RLProductDiscountDataBean.
    7. Pulse Finalizar. El archivo se abrirá en el editor.
    8. Actualice el bean de datos escribiendo el código siguiente:
      
      package com.myCompany.epromotion.databeans;
      
      import com.ibm.commerce.ras.*;
      import com.ibm.commerce.tools.epromotion.util.*;
      import com.ibm.commerce.tools.epromotion.*;
      import com.ibm.commerce.tools.epromotion.implementations.*;
      import com.ibm.commerce.fulfillment.objects.*;
      import com.myCompany.epromotion.implementations.*;
      import com.myCompany.epromotion.logic.*;
      import com.ibm.commerce.tools.epromotion.databeans.*;
      
      public class ExtendedPromotionDataBean extends com.ibm.commerce.tools.epromotion.databeans.RLProductDiscountDataBean
         implements com.myCompany.epromotion.logic.ExtendedPromotionConstants {
      
            public ExtendedPromotionDataBean() {
               super();
            }
      
            private int rlRequiredItemQty;
            private int rlPromotedItemQty;
            private String rlPromotedProductId;
            private String rlFixCost;
        
            public void setRlRequiredItemQty(int newRlRequiredItemQty) {
               this.rlRequiredItemQty = newRlRequiredItemQty;
            }
            public void setRlPromotedItemQty(int newRlPromotedItemQty) {
               this.rlPromotedItemQty = newRlPromotedItemQty;
            }
            public void setRlPromotedProductId(String newRlPromotedProductId) {
               this.rlPromotedProductId = newRlPromotedProductId;
            }
            public void setRlFixCost(String newRlFixCost) {
               this.rlFixCost = newRlFixCost;
            }
            public int getRlRequiredItemQty() {
               return this.rlRequiredItemQty;
            }
            public int getRlPromotedItemQty() {
               return this.rlPromotedItemQty;
            }
            public String getRlPromotedProductId() {
               return this.rlPromotedProductId;
            }
            public String getRlFixCost() {
               return this.rlFixCost;
            }
            /**
             * Populate method should be implemented based on the new attributes and type.
             * This populate method will handled by TFW parent frame once it is specified
             * in the Notebook.xml configuration.
             */
            public void populate() throws Exception {
               final String methodName = "populate";
               // call super.populate() to get all the RLPromotion object atributes
               super.populate();
               ECTrace.entry(
                  ECTraceIdentifiers.COMPONENT_MERCHANDISING,
                     getClass().getName(),
                     methodName);
               if (this.getCalcodeId() != null) {
                  EproUtil util = new EproUtil();
                  RLPromotionBean rlPromotionBean = new RLPromotionBean();
                  rlPromotionBean.setCalCodeId(this.getCalcodeId());
                  rlPromotionBean.setCommandContext(this.commandContext);
                  rlPromotionBean.setRequestProperties(this.requestProperties);
                  rlPromotionBean.populate();
       
                  // populate the ExtendedPromotionDataBean with RLPromotionBean values
                  RLPromotion rlPromotion = rlPromotionBean.getRLPromotion();
         
                  // The part below is customized for each extended type
                  if (this
                     .getRlPromotionType()
                     .equalsIgnoreCase(PROMOTION_CATEGORYLEVELPWP)) {
                     if (rlPromotion instanceof CategoryLevelPurchaseWithPurchase) {
                        CategoryLevelPurchaseWithPurchase obj =
                        (CategoryLevelPurchaseWithPurchase) rlPromotion;
                        if (obj != null) {
                           this.setRlPromotionCatEntryType("Category");
                           this.setRlPromotionMerchandiseType("Category");
                              if (obj.getCatgpIdentifiers() != null) {
                                 int numOfCatGrps = obj.getCatgpIdentifiers().size();
                                 String[] tempArry = new String[numOfCatGrps];
                                 obj.getCatgpIdentifiers().copyInto(tempArry);
                                 this.setRlPromotionCatGroupCode(tempArry);
                              }
                              if (obj.getCatalogGroupIDs() != null) {
                                 int numOfCatGrps = obj.getCatalogGroupIDs().size();
                                 String[] tempArry = new String[numOfCatGrps];
                                 obj.getCatalogGroupIDs().copyInto(tempArry);
                                 this.setRlPromotionCatGroupID(tempArry);
                              }
                              this.setRlRequiredItemQty(obj.getRequiredItemQty());
                              this.setRlPromotedItemQty(obj.getPromotedItemQty());
                              this.setRlFixCost(obj.getFixCost());
                              this.setRlPromotedProductId(obj.getPromotedProductId());
                              // RLDiscountItemSku is using to retrieve the sku for displaying.
                              this.setRlDiscountItemSku(util.getSKU(obj.getPromotedProductId()));
                        }
                     }
                  }
                  // other customized types will be added here.
               }
            }
         }
      
    9. Guarde el archivo, pero no cierre el entorno de desarrollo.
  6. Actualice el archivo de definición XML del cuaderno de promoción para que refleje el tipo de promoción personalizado. Una vez más, para proteger los datos personalizados, deben crearse en un lugar seguro, separados de los elementos de WebSphere Commerce. Este procedimiento crea un nuevo archivo de definición XML del cuaderno Promoción. Esto no se lleva a cabo en el entorno de desarrollo. Para actualizar este cuaderno:
    1. Cree un directorio nuevo. En este ejemplo, asigne al directorio el nombre WCDE_installdir/xml/myCustomXML/, donde miXMLPersonalizado representa un nombre de directorio personalizado.
    2. Repita este proceso hasta que haya creado la vía de acceso siguiente:
      
      WCDE_installdir/xml/myCustomXML/tools/epromotion/
      
    3. Copie el archivo WCDE_installdir/xml/tools/epromotion/RLPromotionNotebook.xml y muévalo al directorio WCDE_installdir/xml/myCustomXML/tools/epromotion/. No cambie el nombre del archivo.
    4. Abra el archivo RLPromotionNotebook.xml en un editor.
    5. Actualice la definición XML para cargar el bean de datos personalizado. Desplácese al elemento <databean>. Cambie el código de modo que coincida con el ejemplo siguiente:
      
      <databean name="rlpromotion"
      >myCompany.promotions.databeans.ExtendedPromotionDataBean" 
         stoplevel="2" />
      

      Observe que se añade también un atributo nuevo, Add stoplevel = "2". Este atributo indica que el objeto JavaScript también debe cumplimentar los atributos del bean de datos padre de este bean de datos.

    6. Guarde el archivo.
  7. Para crear un archivo XML personalizado en un directorio personalizado es necesario actualizar el valor de XMLPath de la instancia. Este valor indica las ubicaciones en las que la aplicación intentará localizar los archivos XML. Funciona de modo similar a un valor de classpath Java. Esto no se lleva a cabo en el entorno de desarrollo. Para actualizar el valor de XMLPath:
    1. Vaya al directorio WCDE_installdir/xml/config.
    2. Abra el archivo wc-server.xml en un editor.
    3. Desplácese a la sección <ToolsGeneralConfig> del archivo y actualice XMLPath especificando el nombre del directorio personalizado en el valor. Por ejemplo, si el valor XMLPath original es:
      
      XMLPath="tools;tools/devtools;WEB-INF/xml/tools;WEB_INF"
      
      y el directorio personalizado es miXMLPersonalizado, cambie el valor XMLPath por:
      
      XMLPath="myCustomXML;myCustomXML/tools;tools;tools/devtools;WEB-INF/xml/tools;WEB_INF"
      
    4. Guarde el archivo.

    Al cambiar el valor de XMLPath en el archivo de configuración de la instancia se habilita esta personalización solamente para la instancia individual. Todas las demás instancias no incluirán este botón nuevo. Si desea personalizar varias instancias, deberá repetir este paso para cada instancia.

    Aviso

    Cuando se aplican fixpacks o se realizan tareas de migración se pueden sobregrabar los cambios realizados en este archivo.

  8. Cree un nuevo archivo JSP que permita a los usuarios finales crear o modificar el nuevo tipo personalizado, incluida la condición de compra y la bonificación. Para crear este archivo JSP:
    1. En el entorno de desarrollo de HCL Commerce, vaya al directorio CommerceAccelerator/Web Content/tools.
    2. Pulse la carpeta con el botón derecho y seleccione Nuevo y, a continuación, Carpeta. En el campo Nombre de carpeta, especifique custom.
    3. Pulse el botón derecho del ratón sobre la carpeta Web Content/tools/custom, seleccione Nuevo y, a continuación, luego Archivo JSP.
    4. En el campo Nombre de archivo del diálogo Archivo JSP nuevo, escriba CustomizedPWP.jsp.
    5. Vaya a la carpeta Web Content/tools/custom.
    6. Pulse dos veces el archivo nuevo para abrirlo en un editor.
    7. Actualice el archivo JSP del modo siguiente:
      
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <%@ page import="com.ibm.commerce.catalog.beans.CatalogEntryDataBean" %>
      <%@ page import="com.ibm.commerce.tools.epromotion.databeans.RLCatEntrySearchListDataBean" %>
      <%@ page import="com.myCompany.epromotion.databeans.ExtendedPromotionDataBean" %>
      <%@ page import="com.myCompany.epromotion.logic.ExtendedPromotionConstants" %>
      
      <%@include file="../epromotion/epromotionCommon.jsp" %>
      
      <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
      <title>Category Level Purchase with Purchase</title>
      <jsp:useBean id="catBean" scope="page" class="com.ibm.commerce.catalog.beans.CatalogEntryDataBean" />
      <jsp:setProperty property="*" name="catBean" />
      <script>
      var needValidation = false;
      
      </script>
      <%= fPromoHeader%>
      <%
         CommandContext commandContext = (CommandContext) request.getAttribute(ECConstants.EC_COMMANDCONTEXT);
         String storeId = commandContext.getStoreId().toString();
         String catEntryType = null;
         String catEntryId = null;
      
         // ### this javaFlagNotFound is used for javascript validation method to check if the user input is valid or not.
         boolean javaFlagNotFound = true;
         // ### this discountSKU is used to store the user manually input and for SKU validation.
         String discountSKU = request.getParameter("discountSKU");
         String calCodeId = request.getParameter("calCodeId");
         String gotoPanelName = request.getParameter("gotoPanelName");
      
         if ((discountSKU != null) && !(discountSKU.trim().equals("")) )
         {
            RLCatEntrySearchListDataBean searchBean = new RLCatEntrySearchListDataBean();
            searchBean.setCommandContext(commandContext);
      
            searchBean.setSku(discountSKU);
            searchBean.setSkuCaseSensitive("yes");
            searchBean.setSkuOperator("EQUAL");
      
            com.ibm.commerce.beans.DataBeanManager.activate(searchBean, request);
      
            int resultCount =  0;
      
            // Get results from the search query
            CatalogEntryDataBean catalogEntries[] = null;
            catalogEntries = searchBean.getResultList();
            if (catalogEntries != null) {
               resultCount = catalogEntries.length;
            }
            if (resultCount > 0){
               catBean = catalogEntries[0];
               catBean.setCommandContext(searchBean.getCommandContext());
               javaFlagNotFound = false;
               catEntryType = catBean.getType();
               catEntryId = catBean.getCatalogEntryID();
               // This result could be any SKU, including Item/Product/Package
            }
            else {
               javaFlagNotFound = true;
            }
         }
      %>
      
      <script src="/wcs/javascript/tools/common/Util.js">
      </script>
      
      <script language="JavaScript">
      
      var calCodeId = null;
      needValidation = <%= javaFlagNotFound%>;
      
      function initializeState() {
         var cType = '<%=UIUtil.toJavaScript(catEntryType)%>';
         var cId = '<%=UIUtil.toJavaScript(catEntryId)%>';
         var discountSku = '<%=UIUtil.toJavaScript(discountSKU)%>';
         var nextPanel = '<%=UIUtil.toJavaScript(gotoPanelName)%>'
        
         var rlPromo = top.getData("RLPromotion");
         if (rlPromo != null) {
            calCodeId = rlPromo.<%= RLConstants.EC_CALCODE_ID %>;
            parent.put("<%= RLConstants.RLPROMOTION %>",rlPromo);
      
            var pgArray =top.getData("RLPWPPageArray",0);
            if(pgArray != null){
               parent.pageArray = pgArray;
            }
              
         }
         else { 
            if (parent.get) {
               var o = parent.get("<%= RLConstants.RLPROMOTION %>", null);
               calCodeId = o.<%= RLConstants.EC_CALCODE_ID %>;
            }
         }
      
         // Check the calcode_id to see if it's Creation Wizard or Modification Notebook:
         if( calCodeId == null || trim(calCodeId) == ''){
            if(parent.getPanelAttribute("CustomizedPromotionPWPType","hasTab")=="NO") {
               parent.setPanelAccess("CustomizedPromotionPWPType", true);
               parent.setPanelAttribute( "CustomizedPromotionPWPType", "hasTab", "YES" );
               parent.setPanelAccess("RLProdPromoWhat", true);
               parent.setPanelAttribute( "RLProdPromoWhat", "hasTab", "YES" );
               parent.TABS.location.reload();
               parent.setPreviousPanel("RLProdPromoWhat");
            }
            // disable the range panel since we don't use it in this PWP sample.
            parent.setPanelAttribute( "RLProdPromoWizardRanges", "hasTab", "NO" );
            parent.TABS.location.reload();         
         } 
         else {
            parent.setPanelAttribute( "CustomizedPromotionPWPType", "hasTab", "YES" );
            parent.TABS.location.reload();   
         }
       
         if (parent.get) {
            var o = parent.get("<%= RLConstants.RLPROMOTION %>", null);
            var hasMax = false;
            if (o != null) {
               // ### initialize all the form elements by existing object:
               with (document.customizedPWPForm) { 
                  promotedSku.value = o.<%= RLConstants.RLPROMOTION_DISCOUNT_ITEM_SKU %>;
                  fixedCost.value = o.<%= ExtendedPromotionConstants.PROMOTION_FIXCOST %>;
                  if(!isNaN(o.<%= ExtendedPromotionConstants.PROMOTION_PROMOTEDITEMQTY %>))
                  promotedQty.value = o.<%= ExtendedPromotionConstants.PROMOTION_PROMOTEDITEMQTY %>;
                  if(o.<%= ExtendedPromotionConstants.PROMOTION_REQUIREDITEMQTY %> == '1' || 
            o.<%= ExtendedPromotionConstants.PROMOTION_REQUIREDITEMQTY %> == null || 
                     o.<%= ExtendedPromotionConstants.PROMOTION_REQUIREDITEMQTY %> == "")
                     {
                        hasMax = false;
                        maxRad[0].checked=true;
                  }else {
                     if(!isNaN(o.<%= ExtendedPromotionConstants.PROMOTION_REQUIREDITEMQTY %>)) {
                        hasMax = true;
                        maxRad[1].checked=true;
                        minProdPurchaseQty.value = o.<%= ExtendedPromotionConstants.PROMOTION_REQUIREDITEMQTY %>;
                     } 
                  }
                  checkMaxArea(hasMax);
               }
            }  
         }
       
         if (trim(cType) != '' && trim(cId) != '') {
            if (parent.get) {
               var o = parent.get("<%= RLConstants.RLPROMOTION %>", null);
               if (o != null) {
                  o.<%= ExtendedPromotionConstants.PROMOTION_PROMOTEDPRODUCTID %> = "<%=UIUtil.toJavaScript(catEntryId)%>";
               }
            }
            if (calCodeId == null || trim(calCodeId) == '') {
               parent.finish();
            } 
            else {
               if (nextPanel == null || trim(nextPanel) == '' || nextPanel == 'undefined') {
                  parent.finish();
               }
               else {
                  parent.gotoPanel(nextPanel);     
               }
            }
         }
         else {
            if ( (!needValidation && trim(discountSku) != '') && (trim(cType) == null || trim(cType) == '' || trim(cId) == '' || trim(cId) == null)) {
               needValidation = true;
               alertDialog("<%= UIUtil.toJavaScript(RLPromotionNLS.get("RLInvalidItemSKU").toString())%>");      
            }
            else if (needValidation && trim(discountSku) != '') {
               alertDialog("<%= UIUtil.toJavaScript(RLPromotionNLS.get("RLInvalidSKU").toString())%>");
            }
         }
      
         parent.setContentFrameLoaded(true);
      
         if (parent.get("prodQtyTooLong", false)) {
            parent.remove("prodQtyTooLong");
            reprompt(document.customizedPWPForm.promotedQty,"<%= UIUtil.toJavaScript(RLPromotionNLS.get("prodQtyNumberTooLong").toString())%>");
            return;
         }
         if (parent.get("prodQtyNotNumber", false)) {
            parent.remove("prodQtyNotNumber");
            reprompt(document.customizedPWPForm.promotedQty,"<%= UIUtil.toJavaScript(RLPromotionNLS.get("prodMinNotNumber").toString())%>");
            return;
         }
         if (parent.get("reqProdQtyTooLong", false)) {
            parent.remove("reqProdQtyTooLong");
            reprompt(document.customizedPWPForm.minProdPurchaseQty,"<%= UIUtil.toJavaScript(RLPromotionNLS.get("prodQtyNumberTooLong").toString())%>");
            return;
         }
         if (parent.get("reqProdQtyNotNumber", false)) {
            parent.remove("reqProdQtyNotNumber");
            reprompt(document.customizedPWPForm.minProdPurchaseQty,"<%= UIUtil.toJavaScript(RLPromotionNLS.get("prodMinNotNumber").toString())%>");
            return;
         }
         if (parent.get("noSKUEntered", false)) {
            parent.remove("noSKUEntered");
            alertDialog("<%= UIUtil.toJavaScript(RLPromotionNLS.get("SKUNotEntered").toString())%>");
            return;
         }
      }
      function savePanelData() {
         if (parent.get) {
            var o = parent.get("<%= RLConstants.RLPROMOTION %>", null);
            if (o != null) {
               with (document.customizedPWPForm) {
                  o.<%= RLConstants.RLPROMOTION_DISCOUNT_ITEM_SKU %> = promotedSku.value;
                  o.<%= ExtendedPromotionConstants.PROMOTION_FIXCOST %> = fixedCost.value;
                  if (trim(promotedQty.value) != null && trim(promotedQty.value) != "") {
                     o.<%= ExtendedPromotionConstants.PROMOTION_PROMOTEDITEMQTY %> = parent.strToNumber(trim(promotedQty.value),"<%=fLanguageId%>");
                  } 
                  else {
                     o.<%= ExtendedPromotionConstants.PROMOTION_PROMOTEDITEMQTY %> = "";
                  } 
         if (maxRad[1].checked) {
                     if (trim(minProdPurchaseQty.value) != null && trim(minProdPurchaseQty.value) != "")
                     o.<%= ExtendedPromotionConstants.PROMOTION_REQUIREDITEMQTY %> = parent.strToNumber(trim(minProdPurchaseQty.value),"<%=fLanguageId%>");
                     else
                     o.<%= ExtendedPromotionConstants.PROMOTION_REQUIREDITEMQTY %> = "";
                  }
         else {
                     o.<%= ExtendedPromotionConstants.PROMOTION_REQUIREDITEMQTY %> = 1;
                  }
                  if(o.<%= RLConstants.RLPROMOTION_CATENTRY_TYPE %> == 'ProductBean')
                     o.<%= RLConstants.RLPROMOTION_TYPE %> = "<%= ExtendedPromotionConstants.PROMOTION_PRODUCTLEVELPWP %>";
                  else if(o.<%= RLConstants.RLPROMOTION_CATENTRY_TYPE %> == 'ItemBean')
           o.<%= RLConstants.RLPROMOTION_TYPE %> = "<%= ExtendedPromotionConstants.PROMOTION_ITEMLEVELPWP %>";
                  else if(o.<%= RLConstants.RLPROMOTION_CATENTRY_TYPE %> == 'PackageBean')
           o.<%= RLConstants.RLPROMOTION_TYPE %> = "<%= ExtendedPromotionConstants.PROMOTION_ITEMLEVELPWP %>";
                  else if(o.<%= RLConstants.RLPROMOTION_CATENTRY_TYPE %> == 'Category')
           o.<%= RLConstants.RLPROMOTION_TYPE %> = "<%= ExtendedPromotionConstants.PROMOTION_CATEGORYLEVELPWP %>";
               }
            }
         }
         return true;
      }
      
      function validatePanelData() {
         with (document.customizedPWPForm) {
            if(trim(promotedSku.value) == "" || trim(promotedSku.value) == null) {
               alertDialog("<%= UIUtil.toJavaScript(RLPromotionNLS.get("SKUNotEntered").toString())%>");
               return false;
            }
            if(trim(fixedCost.value) == "" || trim(fixedCost.value) == null) {
               alertDialog("The item cost for this promotion is required.");
               return false;
            } 
            else if (!validateCost(fixedCost)) return false;
      
            if (!validateQty(promotedQty)) return false;
            if (maxRad[1].checked) {
               if (!validateQty(minProdPurchaseQty)) return false;
            }
         }
         if (needValidation) {
            this.location.replace("/webapp/wcs/tools/servlet/CustomizedPromotionPWPView?discountSKU=" + document.customizedPWPForm.promotedSku.value);
            return false; // this will force to stay in the same panel
         } else {
            return true; // go to next panel
         } 
      }
      
      function validateNoteBookPanel(gotoPanelName){
         with (document.customizedPWPForm) {
            if(trim(promotedSku.value) == "" || trim(promotedSku.value) == null) {
               alertDialog("<%= UIUtil.toJavaScript(RLPromotionNLS.get("SKUNotEntered").toString())%>");
               return false;
            } 
            if(trim(fixedCost.value) == "" || trim(fixedCost.value) == null) {
               alertDialog("The item cost for this promotion is required.");
               return false;
            } 
            else if (!validateCost(fixedCost)) return false;
      
            if (!validateQty(promotedQty)) return false;
            if (maxRad[1].checked) {
               if (!validateQty(minProdPurchaseQty)) return false;
            }
         }
         if (needValidation) {
            this.location.replace("/webapp/wcs/tools/servlet/CustomizedPromotionPWPView?discountSKU=" + document.customizedPWPForm.promotedSku.value + "&calCodeId=" + calCodeId + "&gotoPanelName="+ gotoPanelName);
            return false; // this will force to stay in the same panel
         } else {
            return true; // go to next panel
         } 
      }
      
      function validateCost(cost) {
         if ( !parent.isValidInteger(trim(cost.value), "<%=fLanguageId%>")) || 
               (!parent.isValidDouble(trim(cost.value), "<%=fLanguageId%>")))  {
            reprompt(cost,"The fixed cost value is not a number.");
            return false;
         } 
         else if (!(eval(parent.strToNumber(trim(cost.value),"<%=fLanguageId%>")) >= 0)) {
            reprompt(cost,"The fixed cost has to be greater than or equals to zero.");
            return false;
         }
         return true;
      }
      
      function validateQty(qtyField) {
         if(parent.strToNumber(trim(qtyField.value),"<%=fLanguageId%>").toString().length > 14) {
            reprompt(qtyField,"<%= UIUtil.toJavaScript(RLPromotionNLS.get("prodQtyNumberTooLong").toString())%>");
            return false;
         }
         else if ( !parent.isValidInteger(trim(qtyField.value), "<%=fLanguageId%>")) {
            reprompt(qtyField,"<%= UIUtil.toJavaScript(RLPromotionNLS.get("prodMinNotNumber").toString())%>");
            return false;
         }
         else if (!(eval(parent.strToNumber(trim(qtyField.value),"<%=fLanguageId%>")) >= 1)) {
            reprompt(qtyField,"<%= UIUtil.toJavaScript(RLPromotionNLS.get("prodMinNotNumber").toString())%>");
            return false;
         }
         return true; 
      }
      
      function checkMaxArea(hasMax) {
         if (hasMax) {
            document.all["maxArea"].style.display = "block";
         }
         else {
            document.all["maxArea"].style.display = "none";
         }
      }
      
      function callSearch() {
         var rlpagename = "CustomizedPromotionPWP";
         savePanelData();
         var productSKU = document.customizedPWPForm.promotedSku.value;
         top.saveModel(parent.model);
         top.saveData(parent.pageArray, "RLPWPPageArray");
         if (parent.get) {
            var o = parent.get("<%= RLConstants.RLPROMOTION %>", null);
            if (o != null) {   
               top.saveData(o,"RLPromotion");
            }
         }
         top.put("inputsku",productSKU);
         // This variable will and value will be used to distinguish which search 
         // function the search page should provide.
         top.put("<%= RLConstants.RLPROMOTION_PROD_SEARCH_PAGE %>",rlpagename);
         top.saveData(productSKU, "inputsku");
         top.setReturningPanel("CustomizedPromotionPWPType");
         top.setContent("<%= RLPromotionNLS.get("ProductSearchBrowserTitle") %>","/webapp/wcs/tools/servlet/RLSearchDialogView?ActionXMLFile=RLPromotion.RLSearchDialog",true);
      }
      
      function setValidationFlag() {
         if(trim(document.customizedPWPForm.promotedSku.value) != '') {
            needValidation = true;
         }
      }
      
      </script>
      <meta name="GENERATOR" content="IBM WebSphere Studio" />
      </head>
      
      <body class="content" onload="initializeState();">
      
      <form name="customizedPWPForm" id="customizedPWPForm">
      
      <h1>Purchase With Purchase</h1>
      <br />
      
      <label for="promotedSkuLabel">Product SKU selected as promoted (required)</label><br />
      <table border="0" cellpadding="0" cellspacing="0" id="customizedPWP_Table_1">
      <tr>
      <td id="customizedPWP_TableCell_1"> 
        <input name="promotedSku" type="text" size="15" maxlength="50" onchange="setValidationFlag()" id="promotedSkuLabel" /> 
      </td>
      <td id="customizedPWP_TableCell_2"> 
        <button type="button" value='Find' name="rlSearchProduct" class="enabled" style="width:auto;text-align:center" onclick="javascript:callSearch();"> Find</button> 
      </td>
      </tr>
      </table>
      
      
      <p><label for="promotedQtyLabel">Number of items to be given for a fixed cost based on purchase (required)</label><br />
      <input name="promotedQty" type="text" size="10" maxlength="14" id="promotedQtyLabel" />
          Items</p>
      <p><label for="fixCostLabel">Fixed cost for each unit of promoted items (required)</label><br />
      <input name="fixedCost" type="text" size="10" maxlength="14" id="fixCostLabel" />
      <script language="JavaScript">
      document.write(parent.getCurrency());
      </script></p>
      
      Minimum qualification<br />
      <input type="radio" name="maxRad" onclick="javascript:checkMaxArea(false);" checked ="checked" id="None" /><label for="None">None</label><br />
      <input type="radio" name="maxRad" onclick="javascript:checkMaxArea(true);" id="MinQty" /><label for="MinQty">Specify a minimum qualification for the promotion</label>
      <div id="maxArea" style="display:none">
       <blockquote>
       <p><label for="purchaseAmount">Required quantity</label><br />
       <input name="minProdPurchaseQty" type="text" size="10" maxlength="14" id="purchaseAmount" />
          Items
       </p>   
       </blockquote>
      </div>
      
      </form>
      </body>
      </html>
      
    8. Guarde el archivo, pero no cierre el entorno de desarrollo.
  9. Cree una vista que corresponda a la página nueva en el archivo de configuración Struts para correlacionar el archivo JSP nuevo con la vista correspondiente.
    • En HCL Commerce versiones 9.0.0.x: Añada las entradas en el archivo struts-config-ext.xml para que apunte a su página JSP personalizada. Todos los cambios de personalización deben realizarse en struts-config-ext.xml, no en struts-config.xml. Para registrar la vista nueva, haga lo siguiente:
      1. En el entorno de desarrollo de HCL Commerce, vaya a la carpeta CommerceAccelerator/Web Content/WEB-INF.
      2. En el menú emergente del archivo struts-config-ext.xml, seleccione Abrir.
      3. Añada el código siguiente:
      
      <global-forwards>
         <forward name="CustomizedPromotionPWPView" path="/tools/custom/CustomizedPWP.jsp" 
            className="com.ibm.commerce.struts.ECActionForward" /> 
      </global-forwards>
      <!-- Action Mappings --> 
      <action-mappings type="com.ibm.commerce.struts.ECActionMapping">
         <action path="/CustomizedPromotionPWPView"
            type="com.ibm.commerce.struts.BaseAction" />
      </action-mappings>
      
    • Añada las entradas en el archivo struts-wcs-accelerator-custom.xml para que apunte a su página JSP personalizada. Para registrar la nueva vista, vaya a la carpeta CommerceAccelerator/src en el entorno de desarrollo de HCL Commerce. En el menú emergente del archivo struts-wcs-accelerator-custom.xml, seleccione Abrir. Añada el código siguiente:
      <action class="com.ibm.commerce.struts.v2.BaseAction" name="CustomizedPromotionPWPView">
      <param name="https">0:1</param>
      <result name="CustomizedPromotionPWPView">
      <param name="location">/tools/custom/CustomizedPWP.jsp</param>
      <param name="resourceClassName">com.ibm.commerce.tools.command.ToolsForwardViewCommandImpl</param>
      </result>
      </action>
  10. Actualice los archivos XML del asistente y el cuaderno para que reconozcan el nuevo tipo de promoción. Para proteger los datos personalizados, se deben crear en un lugar seguro, aparte de los elementos de HCL Commerce. Este procedimiento crea nuevos archivos de definición XML del cuaderno y del asistente de promociones en un directorio nuevo. Esto no se lleva a cabo en el entorno de desarrollo. Para añadir el botón:

    1. Copie el archivo WCDE_installdir/xml/tools/epromotion/RLPromotionWizard.xml y muévalo al directorio WCDE_installdir/xml/myCustomXML/tools/epromotion.
    2. Vaya al directorio WCDE_installdir/xml/myCustomXML/tools/epromotion.
    3. Abra el archivo RLPromotionWizard.xml nuevo en un editor.
    4. Añada el código siguiente al nuevo archivo RLPromotionWizard.xml inmediatamente después de la sección del panel RLDiscountGWPType:
      
      <panel name="CustomizedPromotionPWPType"
         url="CustomizedPromotionPWPView"
         helpKey=""
         hasTab="NO"
         hasNext="NO" 
         hasFinish="YES" />
      
    5. Guarde y cierre el archivo.
    6. Abra el archivo RLPromotionNotebook.xml que previamente se ha modificado en el paso 6, en un editor.
    7. Añada el código siguiente al nuevo archivo RLPromotionNotebook.xml inmediatamente después de la sección del panel RLDiscountGWPType:
      
        <panel name="CustomizedPromotionPWPType"
         url="CustomizedPromotionPWPView"
         helpKey=""
         hasTab="NO" />
      
    8. Guarde y cierre el archivo.
  11. Registre el nuevo tipo de objeto Java para que lo utilice la fábrica de promociones. Para actualizar el registro, añada el código siguiente al archivo workspace_dir\WC\xml\tools\epromotion\RLPromotion.xml:
    
      <type name="CategoryLevelPurchaseWithPurchase"
         className="com.myCompany.promotions.implementations.CategoryLevelPurchaseWithPurchase"
         mappingFileRelativePath="" />
    
  12. Modifique el nuevo archivo CustomizedPWP.jsp para que maneje correctamente el flujo de paneles del asistente y el cuaderno.
    1. Añada la siguiente sentencia import en la parte superior del JSP para que incluya el objeto de bean de datos ampliado:
      <%@ page import="com.ibm.commerce.tools.epromotion.ExtendedPromotionConstants" %>
    2. Cree un formulario para visualizar y procesar los elementos de condición de compra.
    3. Modifique los métodos siguientes:
      • initializeState(),
      • savePanelData(),
      • validatePanelData(),
      • validateNoteBookPanel().
      Asimismo, actualice cualquier método relacionado, como corresponda.
    4. Si el tipo de promoción lo requiere, actualice el método validateAllPanels en el archivo siguiente:

      Web Content/javascript/tools/epromotion/rlDiscountNotebook.js

    5. Guarde el archivo, pero no cierre el entorno de desarrollo.
  13. Actualice el archivo RLPromotionProperties.jsp para que dé soporte al nuevo tipo de promoción y vista. Para actualizar este archivo JSP:
    1. En el entorno de desarrollo HCL Commerce, vaya a CommerceAccelerator/Web Content/tools/epromotion, pulse con el botón derecho del ratón en el archivo RLPromotionProperties.jsp y seleccione Copiar.
    2. Pulse con el botón derecho sobre la carpeta Web Content/tools/custom y seleccione Pegar.
    3. Vaya a la carpeta Web Content/tools/custom.
    4. Pulse dos veces el archivo nuevo para abrirlo en un editor.
    5. Dado que el archivo personalizado está en una ubicación diferente, tiene que actualizar la vía de acceso siguiente en el archivo JSP de modo que refleje la ubicación original. Busque la siguiente sentencia include:
      
      <%@include file="epromotionCommon.jsp" %>
      

      y cámbiela por:

      
      <%@include file="../epromotion/epromotionCommon.jsp" %>
      
    6. Asimismo, debe añadir una sentencia include para importar la lógica personalizada. Añada lo siguiente al bloque include:
      
      <%@include file="com.myCompany.epromotion.logic.*" %>
      
    7. Actualice la inicialización del panel en la sección superior del JSP. Localice el código siguiente:
      
               } else if (o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= RLConstants.RLPROMOTION_ITEMLEVELBUYXGETYFREE %>" 
                      || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= RLConstants.RLPROMOTION_PRODUCTLEVELBUYXGETYFREE %>"
                      || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= RLConstants.RLPROMOTION_CATEGORYLEVELBUYXGETYFREE %>"){
                   parent.setPanelAttribute( "RLProdPromoWhat", "hasTab", "YES");
                   parent.setPanelAttribute( "RLProdPromoGWPType", "hasTab", "YES" );
                   parent.reloadFrames();
               }
            }
            else {
               parent.setPanelAttribute( "RLProdPromoWizardRanges", "hasTab", "NO" );
               parent.setPanelAttribute( "RLDiscountWizardRanges", "hasTab", "NO" );
               parent.reloadFrames();
            }
         }
      }
      

      y actualícelo de modo que coincida con lo siguiente:

      
               } else if (o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= RLConstants.RLPROMOTION_ITEMLEVELBUYXGETYFREE %>"
                      || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= RLConstants.RLPROMOTION_PRODUCTLEVELBUYXGETYFREE %>"
                      || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= RLConstants.RLPROMOTION_CATEGORYLEVELBUYXGETYFREE %>"){
                    parent.setPanelAttribute( "RLProdPromoWhat", "hasTab", "YES");
                    parent.setPanelAttribute( "RLProdPromoGWPType", "hasTab", "YES" );
                    parent.reloadFrames();
               } else if (o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= ExtendedPromotionConstants.PROMOTION_ITEMLEVELPWP %>" 
                      || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= ExtendedPromotionConstants.PROMOTION_PRODUCTLEVELPWP %>" 
                      || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= ExtendedPromotionConstants.PROMOTION_CATEGORYLEVELPWP %>"){
                    parent.setPanelAttribute( "RLProdPromoWhat", "hasTab", "YES");
                    parent.setPanelAttribute( "CustomizedPromotionPWPType", "hasTab", "YES" );
                    parent.reloadFrames();
               }
            }
            else {
               parent.setPanelAttribute( "RLProdPromoWizardRanges", "hasTab", "NO" );
               parent.setPanelAttribute( "RLDiscountWizardRanges", "hasTab", "NO" );
               parent.reloadFrames();
            }
         }
      }
      
    8. Actualice la función initializePromotionType para añadir un nuevo tipo de promoción a la lista desplegable. La función actualizada debe coincidir con el código siguiente, aunque algunas líneas se han partido para facilitar su visualización:
      
      function initializePromotionType() {
         document.propertiesForm.rlPromotionType.options[0] = new Option("<%=RLPromotionNLS.get("percentOffPerItem")%>", 
            "<%= RLConstants.RLPROMOTION_PRODUCTLEVELPERCENTDISCOUNT %>", true, true);
         document.propertiesForm.rlPromotionType.options[1] = new Option("<%=RLPromotionNLS.get("fixedAmountOffPerItem")%>", 
            "<%= RLConstants.RLPROMOTION_PRODUCTLEVELPERITEMVALUEDISCOUNT %>", false, false);
         document.propertiesForm.rlPromotionType.options[2] = new Option("<%=RLPromotionNLS.get("fixedAmountOffAll")%>", 
            "<%= RLConstants.RLPROMOTION_PRODUCTLEVELVALUEDISCOUNT %>", false, false);
         document.propertiesForm.rlPromotionType.options[3] = new Option("<%=RLPromotionNLS.get("buyXGetY")%>",  
            "<%= RLConstants.RLPROMOTION_ITEMLEVELSAMEITEMPERCENTDISCOUNT %>", false, false);
         document.propertiesForm.rlPromotionType.options[4] = new Option("<%=RLPromotionNLS.get("freeGiftWithPurchase")%>", 
            "<%= RLConstants.RLPROMOTION_PRODUCTLEVELBUYXGETYFREE %>", false, false);
         document.propertiesForm.rlPromotionType.options[5] = new Option("Purchase with Purchase",
            "<%= ExtendedPromotionConstants.PROMOTION_CATEGORYLEVELPWP %>", false, false);
      }
      
    9. Actualice la función initializeState para inicializar el nuevo tipo de promoción. Localice el código siguiente:
      
       
      } else if (o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= RLConstants.RLPROMOTION_ITEMLEVELBUYXGETYFREE %>" 
            || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= RLConstants.RLPROMOTION_PRODUCTLEVELBUYXGETYFREE %>" 
            || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= RLConstants.RLPROMOTION_CATEGORYLEVELBUYXGETYFREE %>"){
         document.propertiesForm.rlPromotionGroup.options[0].selected = true;
         refreshPromoTypeAndCombinationFields(document.propertiesForm.rlPromotionGroup); 
         document.propertiesForm.rlPromotionType.options[4].selected = true;
         lastGroup = 0;
         lastType = 4;
      }
      

      Inmediatamente después de este código, inserte el código siguiente:

      
       
      else if (o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= ExtendedPromotionConstants.PROMOTION_CATEGORYLEVELPWP %>" 
            || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= ExtendedPromotionConstants.PROMOTION_PRODUCTLEVELPWP %>" 
            || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= ExtendedPromotionConstants.PROMOTION_ITEMLEVELPWP %>"){
         document.propertiesForm.rlPromotionGroup.options[0].selected = true;
         refreshPromoTypeAndCombinationFields(document.propertiesForm.rlPromotionGroup);       
         document.propertiesForm.rlPromotionType.options[5].selected = true;
         lastGroup = 0;
         lastType = 5;
      }
      
    10. Actualice la función refreshPromoTypeAndCombinationFields(promGroup) para el nuevo tipo. La función actualizada debe coincidir con el código siguiente, aunque algunas líneas se han partido para facilitar su visualización. El código actualizado se restalta en negrita. Asimismo, tenga en cuenta que este es solo un ejemplo parcial, que ilustra el principio de la función pero incluye todos los cambios necesarios:
      function refreshPromoTypeAndCombinationFields(promGroup) {
         var length = document.propertiesForm.rlPromotionType.options.length;
         for(var i=length-1; i>=0; i--) {
            document.propertiesForm.rlPromotionType.options[i] = null;
         }
      
         var length = document.propertiesForm.inCombination.options.length;
         for(var i=length-1; i>=0; i--) {
            document.propertiesForm.inCombination.options[i] = null;
         }
      
         if(promGroup.options[0].selected) {
            document.propertiesForm.rlPromotionType.options[0] = new Option("<%=RLPromotionNLS.get("percentOffPerItem")%>", 
                  "<%= RLConstants.RLPROMOTION_PRODUCTLEVELPERCENTDISCOUNT %>", true, true);
            document.propertiesForm.rlPromotionType.options[1] = new Option("<%=RLPromotionNLS.get("fixedAmountOffPerItem")%>", 
                  "<%= RLConstants.RLPROMOTION_PRODUCTLEVELPERITEMVALUEDISCOUNT %>", false, false);
            document.propertiesForm.rlPromotionType.options[2] = new Option("<%=RLPromotionNLS.get("fixedAmountOffAll")%>", 
                  "<%= RLConstants.RLPROMOTION_PRODUCTLEVELVALUEDISCOUNT %>", false, false);
            document.propertiesForm.rlPromotionType.options[3] = new Option("<%=RLPromotionNLS.get("buyXGetY")%>",  
                  "<%= RLConstants.RLPROMOTION_ITEMLEVELSAMEITEMPERCENTDISCOUNT %>", false, false);
            document.propertiesForm.rlPromotionType.options[4] = new Option("<%=RLPromotionNLS.get("freeGiftWithPurchase")%>", 
                  "<%= RLConstants.RLPROMOTION_PRODUCTLEVELBUYXGETYFREE %>", false, false);
            document.propertiesForm.rlPromotionType.options[5] = new Option("Purchase with Purchase", 
                  "<%= ExtendedPromotionConstants.PROMOTION_CATEGORYLEVELPWP %>", false, false);
        .
        .
        .
      
    11. Guarde el archivo, pero no cierre el entorno de desarrollo.
  14. Actualice RLProdPromoWhat.jsp para que maneje el flujo del asistente y el destino de promoción nuevo correctamente. Para actualizar este archivo JSP:
    1. En el entorno de desarrollo de HCL Commerce, vaya a la carpeta CommerceAccelerator/Web Content/tools/epromotion. Pulse con el botón derecho sobre el archivo RLProdPromoWhat.jsp y seleccione Copiar.
    2. Pulse con el botón derecho sobre la carpeta Web Content/tools/custom y seleccione Pegar.
    3. Vaya a la carpeta Web Content/tools/custom.
    4. Pulse dos veces el archivo nuevo para abrirlo en un editor.
    5. Dado que el archivo personalizado está en una ubicación diferente, tiene que actualizar la vía de acceso siguiente en el archivo JSP de modo que refleje la ubicación original. Busque la siguiente sentencia include:
      
      <%@include file="epromotionCommon.jsp" %>
      

      y cámbiela por:

      
      <%@include file="../epromotion/epromotionCommon.jsp" %>
      
    6. Asimismo, debe añadir una sentencia include para importar la lógica personalizada. Añada lo siguiente al bloque include:
      
      <%@include file="com.myCompany.epromotion.logic.*" %>
      
    7. Actualice la función initializeState, que requiere varias adiciones:
      1. Este es el inicio de la función actualizada. Tenga en cuenta que se trata solamente de un ejemplo de código parcial que ilustra el principio de la función pero incluye todos los cambios necesarios resaltados en negrita:
        
        function initializeState() {
           var fromSearchPage = top.get("fromSearchPage");
           // If the user has returned from search page., get RLPromotion object 
           // from top and put it in parent
           if(fromSearchPage != 'undefined' && fromSearchPage == true) {
              top.put("fromSearchPage", false);
              var rlPromo = top.getData("RLPromotion");
              parent.put("<%= RLConstants.RLPROMOTION %>", rlPromo);   
           }
          
           var obj = parent.get("<%= RLConstants.RLPROMOTION %>", null); // Get the object from parent
           if (obj!= null)  { 
              calCodeId = obj.<%= RLConstants.EC_CALCODE_ID %>;
              // merchanType is using to store the type of targeted items: Category, ProductBean, ItemBean
              merchanType = obj.<%= RLConstants.RLPROMOTION_MERCHANDISE_TYPE %>;      
           }
           else {   
              merchanType = top.get("<%= RLConstants.RLPROMOTION_MERCHANDISE_TYPE%>"); 
           }
           if(parent.getPanelAttribute( "RLProdPromoWizardRanges", "hasTab") == "NO") {
              parent.setPanelAttribute( "RLProdPromoWhat", "hasTab", "YES" );
              parent.TABS.location.reload();
           }
            
           if ((merchanType != null) && (merchanType != '')) {
              // if Category already been selected before, do following initilzation:
              if(isPWPType()) {
                 merchanType = 'Category';
              }
              if(merchanType =='Category')
        .
        .
        . 
        
      2. Esta sección inhabilita la selección de artículos y productos para las promociones del nuevo tipo. Tenga en cuenta que este es solamente un ejemplo de código parcial. Todos los cambios se resaltan en negrita:
        
        .
        .
        .
        if(catList != null && catList.length > 0) {
           document.whatForm.merchandise[2].checked=true;
           document.whatForm.merchandise[2].focus();
           document.all["categorySelect"].style.display = "block";
           if (calCodeId != null && trim(calCodeId) != '' ) {
              document.whatForm.merchandise[0].disabled=true;
              document.whatForm.merchandise[1].disabled=true;
           }
           if (isPWPType()) {
              document.whatForm.merchandise[0].disabled=true;
              document.whatForm.merchandise[1].disabled=true;
           }
           
           for (var i=0; i<catList.length; i++) {
              var nextOptionIndex = document.whatForm.rlCgryList.options.length;
              var createOption = true;
              for (var j=0; j<badCgryArray.length; j++) {
                 if (catList[i] != 'undefined') {
                    if(catList[i] == badCgryArray[j]){
                       createOption = false; 
                       break;
                    }
                 }
              }
              if (createOption) {
                 document.whatForm.rlCgryList.options[nextOptionIndex] = new Option(
                 catList[i], // name
                 catList[i], // value
                 false,    // defaultSelected
                 false);   // selected 
              }
           }
        }
        else {
           document.whatForm.merchandise[2].checked=true;
           document.whatForm.merchandise[2].focus();
           document.all["categorySelect"].style.display = "block";
           if (isPWPType()) {
              document.whatForm.merchandise[0].disabled=true;
              document.whatForm.merchandise[1].disabled=true;
           }
        }
        document.whatForm.rlCgryName.value = "";
        .
        .
        .
        
      3. Finalmente, hay dos lugares más que requieren personalización, cerca del final de la función initializeState. Tenga en cuenta, que se trata solamente de un ejemplo de código parcial, pero incluye todos los cambios necesarios resaltados en negrita. El fragmento de código debería incluirse al final de la función:
        
           .
           .
           .
           else {
              if (parent.get) {
                 var o = parent.get("<%= RLConstants.RLPROMOTION %>", null);
                 if ((o != null) && (o.<%= RLConstants.RLPRODPROMO_TYPEALIAS %> == "<%= ExtendedPromotionConstants.PROMOTION_CATEGORYLEVELPWP %>")) {
                    document.whatForm.merchandise[2].checked=true;
                    document.whatForm.merchandise[2].focus();
                    showCategorySelectFields();
                    document.whatForm.merchandise[0].disabled=true;
                    document.whatForm.merchandise[1].disabled=true;
                 }   
                 else // In creation when the page is loaded first time, select Product promotion radio button by default
                    {
                    document.whatForm.merchandise[0].checked=true;
                    document.whatForm.merchandise[0].focus();
                    showProductSelectFields(); 
                 }
              }
              else {
                 document.whatForm.merchandise[0].checked=true;
                 document.whatForm.merchandise[0].focus();
                 showProductSelectFields(); 
              }
           }
         
           // initialize the notebook panel:  
              if (parent.get) {
              var o = parent.get("<%= RLConstants.RLPROMOTION %>", null);
              if (o != null) {
                 calCodeId = o.<%= RLConstants.EC_CALCODE_ID %>;
                 whichDiscountType = o.<%= RLConstants.RLPROMOTION_TYPE %>;
                 if( calCodeId != null && calCodeId != '') {
                    if( whichDiscountType != null || whichDiscountType != '') {
                       var pgArray = top.getData("RLProdPromoWhatPageArray");
                       if(pgArray != null) {
                          parent.pageArray = pgArray;
                       }
                       if (whichDiscountType == "<%= RLConstants.RLPROMOTION_ITEMLEVELPERCENTDISCOUNT %>" 
                             || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= RLConstants.RLPROMOTION_PRODUCTLEVELPERCENTDISCOUNT %>" 
                             || whichDiscountType == "<%= RLConstants.RLPROMOTION_CATEGORYLEVELPERCENTDISCOUNT %>"
                             || whichDiscountType == "<%= RLConstants.RLPROMOTION_ITEMLEVELPERITEMVALUEDISCOUNT %>" 
                             || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= RLConstants.RLPROMOTION_PRODUCTLEVELPERITEMVALUEDISCOUNT %>" 
                             || whichDiscountType == "<%=  RLConstants.RLPROMOTION_CATEGORYLEVELPERITEMVALUEDISCOUNT  %>"
                             || whichDiscountType == "<%= RLConstants.RLPROMOTION_ITEMLEVELVALUEDISCOUNT %>" 
                             || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= RLConstants.RLPROMOTION_PRODUCTLEVELVALUEDISCOUNT %>" 
                             || whichDiscountType == "<%=  RLConstants.RLPROMOTION_CATEGORYLEVELVALUEDISCOUNT %>"){
                          parent.setPanelAttribute( "RLProdPromoWizardRanges", "hasTab", "YES" );
                          parent.TABS.location.reload();
                       }else if (whichDiscountType == "<%= RLConstants.RLPROMOTION_ITEMLEVELSAMEITEMPERCENTDISCOUNT %>" 
                             || whichDiscountType == "<%= RLConstants.RLPROMOTION_PRODUCTLEVELSAMEITEMPERCENTDISCOUNT %>" 
                             || whichDiscountType == "<%=  RLConstants.RLPROMOTION_CATEGORYLEVELSAMEITEMPERCENTDISCOUNT %>"){
                          parent.setPanelAttribute( "RLProdPromoBXGYType", "hasTab", "YES" );
                          parent.TABS.location.reload();
                       }else if (whichDiscountType == "<%= RLConstants.RLPROMOTION_ITEMLEVELBUYXGETYFREE %>" 
                             || o.<%= RLConstants.RLPROMOTION_TYPE %> == "<%= RLConstants.RLPROMOTION_PRODUCTLEVELBUYXGETYFREE %>" 
                             || whichDiscountType == "<%=  RLConstants.RLPROMOTION_CATEGORYLEVELBUYXGETYFREE %>"){
                          parent.setPanelAttribute( "RLProdPromoGWPType", "hasTab", "YES" );
                          parent.TABS.location.reload();
                       }
                       else if (whichDiscountType == "<%= ExtendedPromotionConstants.PROMOTION_ITEMLEVELPWP %>" 
                             || whichDiscountType == "<%= ExtendedPromotionConstants.PROMOTION_PRODUCTLEVELPWP %>" 
                             || whichDiscountType == "<%=  ExtendedPromotionConstants.PROMOTION_CATEGORYLEVELPWP %>"){
                          parent.setPanelAttribute( "CustomizedPromotionPWPType", "hasTab", "YES" );
                          parent.TABS.location.reload();
                       }
                    }  //end of if whichDiscountType.
                 }  // end of calcode!=null
              } // end if o!=null
           } // end if parent.get
        
           parent.setContentFrameLoaded(true);
        
           if (parent.get("CategoryNotEntered", false)) {
              parent.remove("CategoryNotEntered");
              alertDialog('<%= UIUtil.toJavaScript(RLPromotionNLS.get("CategoryNotEntered").toString())%>');
              return;
           }
        
           if (parent.get("PurchaseSKUNotEntered", false)) {
              parent.remove("PurchaseSKUNotEntered");
              alertDialog('<%= UIUtil.toJavaScript(RLPromotionNLS.get("PurchaseSKUNotEntered").toString())%>');
              return;
           }
           
           if (parent.get("cannotBeAProduct", false)) {
              parent.remove("cannotBeAProduct");
              alertDialog('<%= UIUtil.toJavaScript(RLPromotionNLS.get("cannotBeAProduct").toString())%>');
              return;
           }
        
        } // end Initialize state
        
    8. Actualice la función savePanelData para añadir el nuevo tipo de promoción, de modo que maneje correctamente el flujo de paneles. La función actualizada debe coincidir con el código siguiente, aunque algunas líneas se han partido para facilitar su visualización. Asimismo, tenga en cuenta que sólo es un ejemplo parcial, pero incluye todos los cambios necesarios. El fragmento de código debería incluirse al final de la función:
      
            .
            .
            .
                  o.<%= RLConstants.RLPROMOTION_CATGROUP_CODE %> = tempCgryList;     
                  if (calCodeId == null || trim(calCodeId) == '') { 
                     var ranges = o.<%= RLConstants.RLPROMOTION_RANGES %>;
                     var values = o.<%= RLConstants.RLPROMOTION_VALUES %>;
                     if(ranges.length > 2 || (ranges.length == 2 && eval(values[0]) != 0) ) {
                        parent.setNextBranch("RLProdPromoWizardRanges");
                     }
                     else if(o.<%= RLConstants.RLPRODPROMO_TYPEALIAS %> == "<%= RLConstants.RLPROMOTION_PRODUCTLEVELPERCENTDISCOUNT %>") {
                        o.<%= RLConstants.RLPROMOTION_TYPE %> = "<%= RLConstants.RLPROMOTION_CATEGORYLEVELPERCENTDISCOUNT %>";
                        parent.setNextBranch("RLProdPromoPercentType");
                     }
                     else if(o.<%= RLConstants.RLPRODPROMO_TYPEALIAS %> == "<%= RLConstants.RLPROMOTION_PRODUCTLEVELPERITEMVALUEDISCOUNT %>") {
                        o.<%= RLConstants.RLPROMOTION_TYPE %> = "<%= RLConstants.RLPROMOTION_CATEGORYLEVELPERITEMVALUEDISCOUNT %>";
                        parent.setNextBranch("RLProdPromoFixedType");
                     }
                     else if(o.<%= RLConstants.RLPRODPROMO_TYPEALIAS %> == "<%= RLConstants.RLPROMOTION_PRODUCTLEVELVALUEDISCOUNT %>") {
                        o.<%= RLConstants.RLPROMOTION_TYPE %> = "<%= RLConstants.RLPROMOTION_CATEGORYLEVELVALUEDISCOUNT %>";
                        parent.setNextBranch("RLProdPromoFixedType");
                     }
                     else if(o.<%= RLConstants.RLPRODPROMO_TYPEALIAS %> == "<%= RLConstants.RLPROMOTION_ITEMLEVELSAMEITEMPERCENTDISCOUNT %>") {
                        o.<%= RLConstants.RLPROMOTION_TYPE %> = "<%= RLConstants.RLPROMOTION_ITEMLEVELSAMEITEMPERCENTDISCOUNT %>";
                        parent.setNextBranch("RLProdPromoBXGYType");
                     }
                     else if(o.<%= RLConstants.RLPRODPROMO_TYPEALIAS %> == "<%= RLConstants.RLPROMOTION_PRODUCTLEVELBUYXGETYFREE %>") {
                        o.<%= RLConstants.RLPROMOTION_TYPE %> = "<%= RLConstants.RLPROMOTION_CATEGORYLEVELBUYXGETYFREE %>";
                        parent.setNextBranch("RLProdPromoGWPType");
                     }
                     else if(o.<%= RLConstants.RLPRODPROMO_TYPEALIAS %> == "<%= ExtendedPromotionConstants.PROMOTION_CATEGORYLEVELPWP %>") {
                        o.<%= RLConstants.RLPROMOTION_TYPE %> = "<%= ExtendedPromotionConstants.PROMOTION_CATEGORYLEVELPWP %>";
                        parent.setNextBranch("CustomizedPromotionPWPType");
                     }
                  } 
               }
               o.<%= RLConstants.RLPROMOTION_CATENTRY_TYPE %> = trim(skuType );  
            }
         }
      }  
      
    9. Cree una función isPWPType. Para añadir esta función, inserte el código siguiente:
      
      function isPWPType() {
         if (parent.get) {    
            var o = parent.get("<%= RLConstants.RLPROMOTION %>", null);
            if ((o != null) && (o.<%= RLConstants.RLPRODPROMO_TYPEALIAS %> == 
                  "<%= ExtendedPromotionConstants.PROMOTION_CATEGORYLEVELPWP %>")) {
               return true;
            }
         else {
               return false;
            }
         }
         else {
            return false;
         }
      }
      
    10. Guarde el archivo, pero no cierre el entorno de desarrollo.
  15. Cree una etiqueta para el panel del asistente. HCL Commerce está diseñado de modo que separa la lógica del programa de las series visualizadas, por lo tanto, las etiquetas para los botones y todos los demás elementos de la interfaz se almacenan en los archivos de propiedades, a los que se hace referencia también como paquetes de recursos. Para evitar que los datos personalizados se sobregraben durante la migración a una versión posterior, o durante la instalación de un fixpack posterior o similar, deben crearse en un lugar seguro, separados de los elementos de HCL Commerce. Este procedimiento crea un archivo de propiedades nuevo, en una carpeta nueva, dentro del entorno de desarrollo de HCL Commerce:
    1. En el entorno de desarrollo de HCL Commerce, vaya al proyecto WebSphereCommerceServerExtensionsLogic.
    2. Vaya a la carpeta src.
    3. Pulse con el botón derecho del ratón sobre la carpeta src, seleccione Nuevo y luego Paquete.
    4. En el campo Nombre del diálogo Paquete Java nuevo, escriba un nombre exclusivo. En este ejemplo, escriba com.myCompany.epromotion.properties, donde myCompany representa un nombre de imagen personalizado. Los paquetes creados por IBM, que se incluyen en HCL Commerce, siguen un convenio de denominación que empieza por com.ibm...
    5. Pulse Finalizar para crear el paquete.
    6. Pulse la carpeta com.myCompany.epromotion.properties con el botón derecho y seleccione Nuevo y, a continuación, Otros. En el diálogo Nuevo, pulse Simple, Archivo y luego Siguiente.
    7. En el campo Nombre de archivo, escriba un nombre exclusivo. Para fines de este ejemplo, escriba RLPromotionNLS_locale.properties, donde locale representa el entorno local desde el que los usuarios de la empresa accederán a HCL Commerce Accelerator.
    8. Pulse Finalizar para crear el archivo y abrirlo en un editor.
    9. Para simplificar el mantenimiento posterior, se recomienda incluir comentarios en este archivo nuevo. Este paso es opcional pero se recomienda llevarlo a cabo. En la parte superior de este archivo, incluya algunos comentarios similares a los siguientes que aclaren la finalidad del archivo:
      
      #
      # Customized properties for Promotions
      #
      # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
      
    10. Desplácese hacia abajo y cree una sección denominada "Definiciones de botones" para este archivo e inserte una etiqueta para el botón nuevo. Esto debería ser similar al ejemplo siguiente:
      
      #
      # Wizard labels
      #
      
      CustomizedPromotionPWPType=Purchase Condition
      
    11. Guarde el archivo, pero no cierre el entorno de desarrollo.

    De este modo, las etiquetas estarán en el idioma del entorno local que ha especificado cuando ha creado el archivo. Si desea entrar una serie en más de un idioma, debe realizar este paso para cada idioma, creando un archivo para cada uno de los entornos locales correspondientes.

    Si un usuario de empresa intenta acceder a esta página utilizando un entorno local para el que no existe un soporte explícito, la infraestructura de herramientas tomará por omisión el archivo RLPromotionNLS.properties, que no contendrá una serie correspondiente. Debería asegurarse de crear una versión del archivo de propiedades para cada entorno local que espera que utilicen los usuarios.

  16. Cuando crea un archivo properties personalizado, debe actualizar el archivo resources.xml adecuado, de modo que el archivo nuevo esté disponible para las herramientas contenidas en dicho componente. Esto no se lleva a cabo en el entorno de desarrollo. Para llevar a cabo esta actualización:
    1. Copie el archivo WCDE_installdir/xml/tools/epromotion/resources.xml y muévalo al directorio WCDE_installdir/xml/myCustomXML/tools/epromotion/.
    2. Abra el archivo resources.xml nuevo en un editor.
    3. Desplácese a la sección "Resourcebundle" del archivo y actualice el código de modo que coincida con el ejemplo siguiente:
      
      <resourceBundle name="RLPromotionNLS">
          <bundle>com.ibm.commerce.tools.campaigns.properties.RLPromotionNLS</bundle>
          <bundle>com.myCompany.epromotions.properties.RLPromotionNLS</bundle> 
      </resourceBundle>
      
      donde myCompany representa el nombre de su directorio personalizado.
    4. Guarde el archivo.

    Tenga en cuenta que el archivo de propiedades original se encuentra en el paquete tools.campaigns.properties. Esto es resultado de una limitación de desarrollo de una versión anterior y no es un error.

  17. Actualice RLProductSearchResult.jsp para que maneje el nuevo tipo de promoción. Para actualizar este archivo JSP:
    1. En el entorno de desarrollo de HCL Commerce, vaya a la carpeta CommerceAccelerator/Web Content/tools/epromotion. Pulse con el botón derecho sobre el archivo RLProductSearchResult.jsp y seleccione Copiar.
    2. Pulse con el botón derecho sobre la carpeta Web Content/tools/custom y seleccione Pegar.
    3. Vaya a la carpeta Web Content/tools/custom.
    4. Pulse dos veces el archivo nuevo para abrirlo en un editor.
    5. Dado que el archivo personalizado está en una ubicación diferente, tiene que actualizar la vía de acceso siguiente en el archivo JSP de modo que refleje la ubicación original. Busque la siguiente sentencia include:
      
      <%@include file="epromotionCommon.jsp" %>
      

      y cámbiela por:

      
      <%@include file="../epromotion/epromotionCommon.jsp" %>
      
    6. Asimismo, debe añadir una sentencia include para importar la lógica personalizada. Añada lo siguiente al bloque include:
      
      <%@ page import="com.myCompany.epromotion.logic.ExtendedPromotionConstants" %>
      
    7. Actualice la inicialización para que maneje el nuevo tipo de promoción. Este código define los elementos de catálogo incluidos en la búsqueda, como elementos, productos o paquetes. Tenga en cuenta que se trata solamente de un ejemplo de código parcial que ilustra el principio de la función pero incluye todos los cambios necesarios resaltados en negrita:
      
        <body onload="onLoad();" class="content_list">
        
        <%
         catEntSearchListBean.setCommandContext(commandContext);
         try {
            // Execute the search bean
            if (fromPage.equals("RLProdPromoWhat")) {
               if (promoType.equalsIgnoreCase("ProductBean")) {
                  catEntSearchListBean.setIsItem(false);
                  catEntSearchListBean.setIsPackage(false);
                  catEntSearchListBean.setIsProduct(true);
                  catEntSearchListBean.setIsDynamicKit(false);
                  catEntSearchListBean.setIsBundle(false);            
               }  
               else if (promoType.equalsIgnoreCase("ItemBean") || promoType.equalsIgnoreCase("PackageBean")) {
                  catEntSearchListBean.setIsItem(true);
                  catEntSearchListBean.setIsPackage(true); // don't care whether item or package. consider it as item
                  catEntSearchListBean.setIsProduct(false);
                  catEntSearchListBean.setIsDynamicKit(false);
                  catEntSearchListBean.setIsBundle(false);
               }
            }
            else if ( fromPage.equals("RLProdPromoGWP") || fromPage.equals("RLDiscountGWP") ) {
               catEntSearchListBean.setIsItem(true);
               catEntSearchListBean.setIsPackage(false);
               catEntSearchListBean.setIsProduct(false);
               catEntSearchListBean.setIsDynamicKit(false);
               catEntSearchListBean.setIsBundle(false);
            }
            else if ( fromPage.equals("CustomizedPromotionPWP")) {
               catEntSearchListBean.setIsItem(true);
               catEntSearchListBean.setIsPackage(true);
               catEntSearchListBean.setIsProduct(true);
               catEntSearchListBean.setIsDynamicKit(false);
               catEntSearchListBean.setIsBundle(false);
            }
            .
            .
            .
      
    8. Actualice la función myRefreshButtons. La función actualizada debe coincidir con el código siguiente, aunque algunas líneas se han partido para facilitar su visualización.
      
      function myRefreshButtons() {
         var fromPage = '<%=fromPage%>';
         var checked = parent.getChecked();
         if(checked.length > 1 && (fromPage == "RLProdPromoGWP" || fromPage == "RLDiscountGWP")) {   
            if(defined(parent.buttons.buttonForm.ButtonAddButton)) {
               parent.buttons.buttonForm.ButtonAddButton.disabled=false;
               parent.buttons.buttonForm.ButtonAddButton.className='disabled';
               parent.buttons.buttonForm.ButtonAddButton.id='disabled';
            }
         }
         if(checked.length > 1 && (fromPage == "CustomizedPromotionPWP")) {   
            if(defined(parent.buttons.buttonForm.ButtonAddButton)) {
               parent.buttons.buttonForm.ButtonAddButton.disabled=false;
               parent.buttons.buttonForm.ButtonAddButton.className='disabled';
               parent.buttons.buttonForm.ButtonAddButton.id='disabled';
            }
         }  
      }
      
    9. Actualice la función addAction para regresar a la página. Tenga en cuenta que se trata solamente de un ejemplo de código parcial, que ilustra el final de la función addAction, pero incluye todos los cambios necesarios resaltados en negrita:
      
           .
           .
           .
         else if (rlpagename == "RLDiscountGWP") {
            var calCodeId = null;
            var rlPromo = top.getData("RLPromotion", 1);
            if (rlPromo != null) {
               rlPromo.<%= RLConstants.RLPROMOTION_DISCOUNT_ITEM_SKU %> =  partNumber[0];
               rlPromo.<%= RLConstants.RLPROMOTION_GWP_CATENTRY_ID %> = catEntryID[0];
               calCodeId = rlPromo.<%= RLConstants.EC_CALCODE_ID %>;
               top.sendBackData(rlPromo,"RLPromotion");
            }
      
            if( (calCodeId == null) || (calCodeId == '') ) {
               top.goBack();
            }else  {
               top.goBack();
            }
         }
         else if (rlpagename == "CustomizedPromotionPWP") {
            var calCodeId = null;
            var rlPromo = top.getData("RLPromotion", 1);
            if (rlPromo != null) {
               rlPromo.<%= RLConstants.RLPROMOTION_DISCOUNT_ITEM_SKU %> = partNumber[0];
               rlPromo.<%= ExtendedPromotionConstants.PROMOTION_PROMOTEDPRODUCTID %> = catEntryID[0];
               calCodeId = rlPromo.<%= RLConstants.EC_CALCODE_ID %>;
               top.sendBackData(rlPromo,"RLPromotion");
            }
            if( (calCodeId == null) || (calCodeId == '') ) {
               top.goBack();               
            }
            else {
               top.goBack();                
            }
         }
      }
      
    10. Guarde el archivo, pero no cierre el entorno de desarrollo.
  18. Actualice RLDiscountDetails.jsp para que maneje el nuevo tipo de promoción. Para actualizar este archivo JSP:
    1. En el entorno de desarrollo de HCL Commerce, vaya a la carpeta CommerceAccelerator/Web Content/tools/epromotion. Pulse con el botón derecho sobre el archivo RLDiscountDetails.jsp y seleccione Copiar.
    2. Pulse con el botón derecho sobre la carpeta Web Content/tools/custom y seleccione Pegar.
    3. Vaya a la carpeta Web Content/tools/custom.
    4. Pulse dos veces el archivo nuevo para abrirlo en un editor.
    5. Dado que el archivo personalizado está en una ubicación diferente, tiene que actualizar la vía de acceso siguiente en el archivo JSP de modo que refleje la ubicación original. Busque la siguiente sentencia include:
      
      <%@include file="epromotionCommon.jsp" %>
      

      y cámbiela por:

      
      <%@include file="../epromotion/epromotionCommon.jsp" %>
      
    6. Asimismo, debe añadir una sentencia include para importar la lógica personalizada. Añada lo siguiente al bloque include:
      
      <%@ page import="com.myCompany.epromotion.implementations.*" %>
      
    7. Actualice la función writeSpecificData. Tenga en cuenta, que se trata solamente un de código de ejemplo parcial, que ilustra los cambios necesarios en la función writeSpecificData. El fragmento de código debería incluirse al final de la función:
      
           .
           .
           .
        <%
         if (rlDiscountDetails.getRLPromotionType().equalsIgnoreCase("CategoryLevelPurchaseWithPurchase")){
            if(rlDiscountDetails.getRLPromotion() instanceof CategoryLevelPurchaseWithPurchase) {
               CategoryLevelPurchaseWithPurchase obj = (CategoryLevelPurchaseWithPurchase) rlDiscountDetails.getRLPromotion();
         Vector cgryEntries = null;
         String promotedSkuString = "";
         String cgryString ="";
         String cgryName ="";  
         if (obj != null) {
                  cgryEntries = obj.getCatgpIdentifiers();   
         String catid = obj.getPromotedProductId();
         promotedSkuString = util.getSKU(catid);   
         %>       
                  document.write('<p><%=UIUtil.toJavaScript(RLPromotionNLS.get("RLCategoryDetails").toString())%> ' + '<br>');
                  <%= UIUtil.toJS("categories", cgryEntries)%>
         <%  
                  for (int i=0; i<cgryEntries.size(); i++) {
                     cgryString = cgryEntries.elementAt(i).toString();
                     cgryName = util.getCategoryName(storeId, langId, cgryString);
         %>     
                     document.write('<i><%=UIUtil.toJavaScript(cgryString ).toString()%></i>');
                     document.write(' (<i><%= UIUtil.toJavaScript(cgryName ).toString()%></i>)');  
                     document.write("<br>");
         <%
               } 
         %> 
                  document.write("</p>");      
         <%
                  if(obj.getRequiredItemQty() == -1 ) {   
         %>
                     document.write('<p>');
                     document.write('<i>Get '+'<%=obj.getPromotedItemQty()%>'+' items of '+'<%=promotedSkuString %>'+' at ' + 
                           '<%=obj.getCurrency()%> <%=obj.getFixCost()%>' + ' with any purchase of required category items.</i>');
                     document.write("</p>");      
         <%
                  }
                  else {
         %>
                     document.write('<p>');
                     document.write('<i>Get '+'<%=obj.getPromotedItemQty()%>'+' items of '+'<%=promotedSkuString %>'+' at ' + 
                           '<%=obj.getCurrency()%> <%=obj.getFixCost()%>' + ' with a minimum purchase of '+ '<%=obj.getRequiredItemQty()%>' + 
                           ' required category items.</i>');
                     document.write("</p>");      
         <%
                  }
               } // end of if (obj != null)
            } 
         }
         %>
      
    8. Guarde el archivo, pero no cierre el entorno de desarrollo.
  19. Para visualizar la descripción de la promoción de un producto, artículo o categoría determinado en la página de inicio de la tienda sin utilizar una iniciativa de campaña. Tiene que rellenar las tablas de relaciones CATENCALCD o CATGPCALCD. Por ejemplo, la promoción A (calcode 1001) se aplica cuando el cliente compra algo de la categoría B (catalogGroupId 200), para proporcionar una bonificación del producto C (catentryId 888) con un descuento del 50 % del precio habitual. Esta relación entre CALCODE 1001 y catalogGroupId 200 se ha de definir en la tabla CATGPCALCD y la relación entre CALCODE 1001 y catentryId 888 se ha de definir en la tabla CATENCALCD. Para dar soporte a esta definición de relación en HCL Commerce Accelerator, efectúe los pasos siguientes:
    1. Amplíe el mandato CreateRLPromotionCmdImpl actual:
      
      public class CustomCreateRLPromotionCmdImpl extends 
          com.ibm.commerce.tools.epromotion.commands.CreateRLPromotionCmdImpl {
      
         /**
          * CustomCreateDiscountCmdImpl constructor.
          */    public CustomCreateRLPromotionCmdImpl() {
                    super();
        
      
      
         /**
          * Create catEntCalcode.
          * @exception com.ibm.commerce.exception.ECSystemException
          *
          */
          public void createCatEntCalCodeBean() throws ECSystemException
          {
              super();
                  if(rlPromotion.getRLPromotionType().equals(RLPROMOTION_CATEGORYLEVELPWP)) {
                  // RLPROMOTION_CATEGORYLEVELPWP is the custom type
                  // registered in the RLPromotion.xml.
                  // Another way to do this if custom type extends from RLItemLevelPromotion type :
                  // if (rlPromotion instanceof RLItemLevelPromotion) {
                  // Populate the CATENCALCD table for all of the products in this 
                  // promotion and calcode. If this type is related to a category, 
                  // then populate the table CATGPCALCD as well.
              }
          }
      
          public void performExecute() throws ECSystemException, ECException {
          try {
              super();
              createCatEntCalCodeBean();
          }   catch (ECException ex)
              {
              throw new ECSystemException(ECMessage._ERR_GENERIC, getClass().getName(),
                     methodName, ex);
              }
              catch (Exception ex)
              {
              throw new ECSystemException(ECMessage._ERR_GENERIC, getClass().getName(), 
                     methodName, ex);
              }}
      }
      
      
      
       
      
    2. Del mismo modo, debe crear un mandato personalizado para actualizar las promociones existentes del nuevo tipo utilizando HCL Commerce Accelerator. Para proporcionar este soporte amplíe el mandato UpdateRLPromotionCmdImpl actual:
      
      public class CustomUpdateRLPromotionCmdImpl extends 
         com.ibm.commerce.tools.epromotion.commands.UpdateRLPromotionCmdImpl {
            public CustomUpdateRLPromotionCmdImpl() {
               super();
            }
      
            public void performExecute() throws com.ibm.commerce.exception.ECException 
            {         
               try {            
                  super();
                  this.updateCatEntCalCode();
                  this.updateCatGpCalCode();
               }            
               catch (Exception e) {
                  throw new ECSystemException(ECMessage._ERR_GENERIC, getClass().getName(), 
                     methodName, e);
               }
            }
      
            public void updateCatEntCalCode() throws ECSystemException 
            {     // Remove the old entries, save the updated entries.
                  // Refer to the createCatEntCalCodeBean() method in 
                  // the CustomCreateRLPromotionCmdImpl command.
            }
      
            public void updateCatGpCalCode() throws ECSystemException 
            {     // Remove the old entries, save the updated entries.
                  // Refer to the createCatEntCalCodeBean() method in 
                  // the CustomCreateRLPromotionCmdImpl command.
            }
      }
      
  20. Actualice las vistas que corresponden a las páginas personalizadas en el archivo de configuración Struts, para correlacionar los archivos JSP nuevos con su correspondiente vista. Los mandatos deben sobregrabarse en el archivo de configuración.
    • En HCL Commerce versiones 9.0.0.x: Añada las entradas en el archivo struts-config-ext.xml para que apunte a su página JSP personalizada. Todos los cambios de personalización deben realizarse en struts-config-ext.xml, no en struts-config.xml. Para registrar las vistas nuevas, haga lo siguiente:
      1. En el entorno de desarrollo de HCL Commerce, vaya a la carpeta CommerceAccelerator/Web Content/WEB-INF.
      2. En el menú emergente del archivo struts-config-ext.xml, seleccione Abrir.
      3. Añada el código siguiente:
        
        <global-forwards>
           <forward name="RLPromotionPropertiesView" path="/tools/custom/RLPromotionProperties.jsp" 
              className="com.ibm.commerce.struts.ECActionForward" /> 
           <forward name="RLProdPromoWhatView" path="/tools/custom/RLProdPromoWhat.jsp" 
              className="com.ibm.commerce.struts.ECActionForward" /> 
           <forward name="RLPromotionProdSearchResultView" path="/tools/custom/RLProductSearchResult.jsp" 
              className="com.ibm.commerce.struts.ECActionForward" /> 
           <forward name="RLDiscountDetailsDialogView" path="/tools/custom/RLDiscountDetails.jsp" 
              className="com.ibm.commerce.struts.ECActionForward" /> 
        </global-forwards>
        <!-- Action Mappings --> 
        <action-mappings type="com.ibm.commerce.struts.ECActionMapping">
           <action path="/RLPromotionPropertiesView"
              type="com.ibm.commerce.struts.BaseAction" /> 
           <action path="/RLProdPromoWhatView" 
              type="com.ibm.commerce.struts.BaseAction" /> 
           <action path="/RLPromotionProdSearchResultView"
              type="com.ibm.commerce.struts.BaseAction" /> 
           <action path="/RLDiscountDetailsDialogView" 
              type="com.ibm.commerce.struts.BaseAction" /> 
        </action-mappings>
        
    • Añada las entradas en el archivo struts-wcs-accelerator-custom.xml para que apunte a su página JSP personalizada. Para registrar las vistas nuevas, haga lo siguiente: En el entorno de desarrollo de HCL Commerce, vaya a la carpeta CommerceAccelerator/src. En el menú emergente del archivo struts-wcs-accelerator-custom.xml, seleccione Abrir.
      Añada el código siguiente:
      <action class="com.ibm.commerce.struts.v2.BaseAction" name="RLPromotionPropertiesView">
      <param name="https">0:1</param>
      <result name="RLPromotionPropertiesView">
      <param name="location">/tools/custom/RLPromotionProperties.jsp</param>
      <param name="resourceClassName">com.ibm.commerce.tools.command.ToolsForwardViewCommandImpl</param>
      </result>
      </action>
      <action class="com.ibm.commerce.struts.v2.BaseAction" name="RLProdPromoWhatView">
      <param name="https">0:1</param>
      <result name="RLProdPromoWhatView">
      <param name="location">/tools/custom/RLProdPromoWhat.jsp</param>
      <param name="resourceClassName">com.ibm.commerce.tools.command.ToolsForwardViewCommandImpl</param>
      </result>
      </action>
      <action class="com.ibm.commerce.struts.v2.BaseAction" name="RLPromotionProdSearchResultView">
      <param name="https">0:1</param>
      <result name="RLPromotionProdSearchResultView">
      <param name="location">/tools/custom/RLProductSearchResult.jsp</param>
      <param name="resourceClassName">com.ibm.commerce.tools.command.ToolsForwardViewCommandImpl</param>
      </result>
      </action>
      <action class="com.ibm.commerce.struts.v2.BaseAction" name="RLDiscountDetailsDialogView">
      <param name="https">0:1</param>
      <result name="RLDiscountDetailsDialogView">
      <param name="location">/tools/custom/RLDiscountDetails.jsp</param>
      <param name="resourceClassName">com.ibm.commerce.tools.command.ToolsForwardViewCommandImpl</param>
      </result>
      </action>
  21. Actualice la tabla CMDREG del registro de mandatos de HCL Commerce para asociar las nuevas implementaciones de mandatos de tarea con la interfaz de mandatos del controlador existente. La siguiente sentencia SQL muestra una actualización de ejemplo:
    
    update CMDREG set CLASSNAME='CustomCreateRLPromotionCmdImpl' where 
        INTERFACENAME='com.ibm.commerce.tools.epromotion.commands.CreateRLPromotionCmd'
    
    
    update CMDREG set CLASSNAME='CustomUpdateRLPromotionCmdImpl' where 
        INTERFACENAME='com.ibm.commerce.tools.epromotion.commands.UpdateRLPromotionCmd'
    
  22. Compruebe la personalización en el entorno de desarrollo. Para completar esta prueba:
    1. Detenga y reinicie la instancia de HCL Commerce.
    2. Inicie el HCL Commerce Accelerator.
    3. En el menú Marketing seleccione Promociones.
    4. Pulse Nueva promoción. Esto iniciará el asistente de promociones, que debería incluir el nuevo tipo de descuento. Cree una promoción utilizando el nuevo tipo.
    5. Examine la tienda utilizando un ID de cliente de prueba. Compile un carro de la compra que satisfaga los criterios de la nueva promoción y determine si la promoción se está aplicando correctamente al pedido. Si funciona como esperaba, entonces la personalización se ha realizado correctamente y puede continuar propagando todos los cambios realizados en el entorno de desarrollo al entorno de producción, como se describe detalladamente en los pasos siguientes. Si no se ha realizado correctamente, tendrá que determinar la causa del error y depurarlo.
  23. Exporte los elementos actualizados. Para exportar los elementos, pulse con el botón derecho en el nuevo archivo CustomizedPWP.jsp y seleccione Exportar. Se abre el asistente para exportación. En el Asistente de exportación:
    1. Seleccione Sistema de archivos y pulse Siguiente.
    2. El archivo CustomizedPWP.jsp estará seleccionado.
    3. Asegúrese de que también selecciona los archivos siguientes:
      • RLPromotionProperties.jsp
      • RLProdPromoWhat.jsp
      • RLProductSearchResult.jsp
      • RLDiscountDetails.jsp
    4. Vaya a la carpeta WebSphereCommerceServerExtensionsLogic/src/com/myCompany/epromotion/logic y seleccione el archivo ExtendedPromotionConstants.
    5. Vaya a la carpeta WebSphereCommerceServerExtensionsLogic/src/com/myCompany/epromotion/implementations y seleccione el archivo CategoryLevelPurchaseWithPurchase.
    6. Vaya a la carpeta WebSphereCommerceServerExtensionsLogic/src/com/myCompany/epromotion/databeans y seleccione el archivo RLProductDisountDatabean.
    7. Vaya a la carpeta WebSphereCommerceServerExtensionsLogic/src/com/myCompany/epromotion/properties y seleccione el archivo RLPromotionsNLS_locale.properties.
    8. Seleccione Crear estructura de directorios para archivos seleccionados.
    9. En el campo En el directorio, escriba un directorio temporal en el que se colocarán los recursos. Por ejemplo, especifique C:\ExportTemp\StoreAssets
    10. Pulse Finalizar.
    11. Si se le solicita, cree el directorio especificado.
  24. Transfiera los elementos actualizados al entorno de producción: Para transferir los archivos:
    1. En la máquina de destino, localice el directorio .ear de la instancia de HCL Commerce. El siguiente es un ejemplo de este directorio:
      • For IBM i OS operating system /QIBM/ProdData/WebAsAdv4/installedApps/ WAS_node_name/ WC_instance_name.ear
      • LinuxAIX /WAS_installdir/installedApps/cellName/ WC_instance_name.ear
      • Windows/WAS_installdir\installedApps\cellName\WC_ instance_name.ear

      Donde:

      instance_name
      Es el nombre de la base de datos de HCL Commerce.
      For IBM i OS operating system WAS_node_name
      For IBM i OS operating systemEl sistema en el que está instalado el producto WebSphere Application Server.
      nombre_célula
      Es el nombre de la célula de WebSphere Application Server.
    2. Copie los archivos exportados del paso 22 anterior, en los directorios siguientes:
      CustomizedPWP.jsp
      WC_eardir/CommerceAccelerator.war/tools/custom
      RLPromotionProperties.jsp
      WC_eardir/CommerceAccelerator.war/tools/custom
      RLProdPromoWhat.jsp
      WC_eardir/CommerceAccelerator.war/tools/custom
      RLProductSearchResult.jsp
      WC_eardir/CommerceAccelerator.war/tools/custom
      RLDiscountDetails.jsp
      WC_eardir/CommerceAccelerator.war/tools/custom
      myCampaignsRB_locale.properties
      WC_eardir/properties/com/myCompany/epromotion/properties
    3. Transfiera los archivos siguientes al entorno de producción:
      /xml/myCustomXML/tools/epromotion/RLPromotionWizard.xml
      Copiar en AppServer/V6/Base/profiles/instance_name/installedApps/WC_instance_name_cell/WC_instance_name.ear/xml/myCustomXML/tools/epromotion/RLPromotionWizard.xml
      /xml/myCustomXML/tools/epromotion/RLPromotionNotebook.xml
      Copiar en AppServer/V6/Base/profiles/instance_name/installedApps/WC_instance_name_cell/WC_instance_name.ear/xml/myCustomXML/tools/epromotion/RLPromotionNotebook.xml
      /xml/myCustomXML/tools/epromotion/resources.xml
      Copiar en AppServer/V6/Base/profiles/instance_name/installedApps/WC_instance_name_ce ll/WC_instance_name.ear/xml/myCustomXML/tools/epromotion/resources.xml
    4. Vuelva a efectuar los cambios realizados en el paso 11 para la versión de tiempo de ejecución del archivo RLPromotion.xml. Este archivo se encuentra en el siguiente directorio:

      AppServer/V6/Base/profiles/instance_name/installedApps/WC_instance_name_ce ll/WC_instance_name.ear/xml/tools/epromotion/

      El cambio necesario es añadir el siguiente bloque de códigos para registrar el nuevo tipo de objeto Java para que lo utilice la fábrica de promociones.
      <type name="CategoryLevelPurchaseWithPurchase" 
         className="com.myCompany.promotions.implementations.CategoryLevelPurchaseWithPur
      chase" 
         mappingFileRelativePath=""/>
      
    5. Actualice el archivo de configuración HCL Commerce.