Showing posts with label hybris. Show all posts
Showing posts with label hybris. Show all posts

Download Excel file functionality in Hybris e-commerce | How to make a excel download in Hybris multi-suite

Download Excel file functionality in Hybris e-commerce | How to make a excel download in Hybris multi-suite

Friends there was a requirnment in Hybris project to create a http link to export data in excel format
implementation
First create a controller and from your controller follow below step

ExcelExportController.java
/**
 *
 */
package com.occ.controller;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.occ.facade.export.ExportFacade;

@Controller
public class ExportController
{

@Autowired
private ExportFacade dlExportFacade;

@RequestMapping(value = "/v1/export", method = RequestMethod.GET)
protected ModelAndView export(final HttpServletRequest request, final HttpServletResponse response) throws Exception
{

final List<Map<String, String>> deal = dlExportFacade.getExportData();
return new ModelAndView("export", "Data", deal);


}

@RequestMapping(value = "/v1/Export", method = RequestMethod.GET)
protected ModelAndView Export(final HttpServletRequest request, final HttpServletResponse response) throws Exception
{

final String output = ServletRequestUtils.getStringParameter(request, "output");
final List<Map<String, String>> deal = dlExportFacade.getExportData();
if (output == null || "".equals(output))
{
//return normal view
// ModelAndView("ExcelExport", "Data", revenueData);
return new ModelAndView("ExcelExport", "Data", deal);

}
else if ("EXCEL".equals(output.toUpperCase()))
{
//return excel view
return new ModelAndView("ExcelExport", "Data", deal);

}
else
{
//return normal view
return new ModelAndView("ExcelExport", "Data", deal);

}
}
}


Facade Layer
DefaultExportFacade.java

/**
 *
 */
package com.occ.facade.export.impl;

import java.util.List;
import java.util.Map;

import com.occ.facade.export.ExportFacade;
import com.occ.service.ExportService;

public class DefaultExportFacade implements ExportFacade
{

/**
* @return the ExportService
*/
public ExportService getExportService()
{
return ExportService;
}

/**
* @param ExportService
*           the ExportService to set
*/
public void setExportService(final ExportService ExportService)
{
this.ExportService = ExportService;
}

public ExportService ExportService;

/*
* (non-Javadoc)
*
* @see com.occ.facade.export.ExportFacade#getExportData()
*/
@Override
public List<Map<String, String>> getExportData()
{

return ExportService.getExportData();
}
}

Service Layer 
ExportService.java
/**
 *
 */
package com.occ.service;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import com.occ.dao.ExportDao;


public class ExportService
{
@Autowired
private ExportDao dlExportDao;

public List<Map<String, String>> getExportData()
{
return dlExportDao.getExportData();
}
}

Excel view

/**
 *
 */
package com.occ.view;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.web.servlet.view.document.AbstractExcelView;


public class ExportView extends AbstractExcelView
{

@Override
protected void buildExcelDocument(final Map model, final HSSFWorkbook workbook, final HttpServletRequest request,
final HttpServletResponse response) throws Exception
{

final List<Map<String, String>> revenueData1 = (List<Map<String, String>>) model.get("Data");

//create a wordsheet
final HSSFSheet sheet = workbook.createSheet(" Export");

final HSSFRow header = sheet.createRow(0);




int rowNum = 1;
for (int i = 0; i < revenueData1.size(); i++)
{
final HSSFRow row = sheet.createRow(rowNum++);
final Map<String, String> data = revenueData1.get(i);


}
}
}

Bean Configuration
 <bean class="org.springframework.web.servlet.view.XmlViewResolver">
<property name="location">
<value>WEB-INF/spring-excel-views.xml</value>
</property>
<property name="order" value="0" />
</bean>

<bean id="viewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
        <property name="prefix">
           <value>/WEB-INF/jsp/</value>
         </property>
        <property name="suffix">
           <value>.jsp</value>
        </property>
        <property name="order" value="1" />
    </bean>


spring-excel-views.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 <bean id="ExcelRevenueSummary" class="com.occ.controller.ExcelRevenueReportView"> </bean>
 <bean id="ExcelExport" class="com.occ.view.DealerExportView"> </bean>
</beans>

Compare IBM WCS vs SAP Hybris vs Oracle ATG | e-commerce features compare

They say "Beauty is in the eyes of the beholder", so if you are a purist in one of these technologies you would probably never agree to my comparison matrix, However these are my personal opinion, From my experience standpoint I have longest exposure to WCS Commerce Suite and the least with ATG Commerce.
Feature comparison are always shallow and should not be taken at face value, they serve a purpose and it is up to you to decide what best suits your implementation, I feel all three of these are excellent commerce products, they serve a different market segment and will continue to have a space for themselves for years to come.
...so at the end of the day you need to do your homework to see what best fits your needs..


IBM WCS(V7, FEP5)

Hybris(5.0)

Oracle ATG(10.2)

Development Environment+1
Complexity associated with development is very high, The system resources required for running IBM RAD and associated WAS Runtime is highest among the three, Organizations are often forced to use VDI which slows down the developer productivity vastly.
+3
Hybris probably ranks no. 1 in this category, the best in terms of supportability for lighter development environment, it can run in an eclipse environment with tomcat container
+2
ATG development environment includes Eclipse, ATG Eclipse Plugin, JBoss
JEE Environment+1
Works only on IBM Websphere Application Servers
+3
Hybris Server (Flavor of Tomcat)
Spring Source TC Server (Flavor of Tomcat)
Oracle Weblogic
IBM WebSphere
+2
Oracle Weblogic
JBOSS
IBM WAS
Total installer size+1

4-10 GB when we include WCS, RAD and WAS test environment
+3

300 MB
+2

710 MB
Development DatabaseApache DerbyHSQLDB databaseMySQL
Production Database+2
Oracle
IBM DB2
+3
Oracle
MySQL
Microsoft SQL Server
+3
IBM DB2
Oracle
Microsoft SQL Server
OS Support+1
Windows
Linux Redhat
IBM AIX
Solaris
+3
Many Flavors(Refer Product documentation)


Windows

Linux
Mac OS
IBM AIX
Solaris
+2
Windows
Linux
Mac OS

Framework Versatility+3
Controller Layer uses a modified version on Struts Framework, Services Layer uses Apache Wink, rest of the framework is IBM custom and the complexity associated with learning and extension of components is probably highest of the three.

+3
Familiar and Flexible programming model as it is based on Spring Framework.

Most probably the purest implementation of Spring without too many custom wrappers, so if you know Spring you already know how to code in Hybris
+1
ATG Custom IOC Container is referred to as “ATG Nucleus“, they were probably the first advocates of IOC containers even before Spring came to lime light.

But things have evolved over time and Spring IOC is far ahead of ATG custom IOC framework.
HTTP Session+3
Zero session footprint, WCS does not use HTTPSession Object, instead the state is maintained in DB tables.

Since the states are saved in DB a node failure does not impact session state and “full session failover” is supported OOB, this works very nicely with both active active and active passive db configuration.


This architecture seems to be of significant advantage in very large scale deployments and session management is natively supported in WCS framework instead of depending on WAS
+2
Depends on JsessionID
Hybris refers to session failover support as “Semi session failover”, so if a node fails it can restore the guest session in a semi state like Guest ID, Cart etc..
+1
Depends on JsessionID and HttpSession features of underlying JEE server.
Out of the box, nothing is persisted to the database until sign-in, but a configuration is available to persist state to DB for anonymous users.
Caching+3
DynaCache for caching within JVM and Advanced support for remote Cache by making use of IBM WXS as a central Cache repository
+2
Hybris Region Cache custom caching framework, can be extended to custom caching provider like EHCache.

Standard Spring annotations are supported for caching objects.


Possibility to plugin other commercial third party caching solutions like

Coherence, Gigaspaces and Memcache
+1

ATG supports custom Distributed hybrid caching
Clustering+2
All of the standard WAS Clustering features, considering WAS is very matured as a JEE server you can leverage all of the standard WAS clustering and failover features
+3
Since Hybris is supported by various JEE container they cannot rely on container clustering features, Hybris Cluster solution is independent of the underlying JEE container.
Support for TCP or UDP based clustering.

Another important feature of Hybris cluster is Multi-Tenant Mode, this gives the flexibility to use a different database prefix for multiple application in the same JVM, WCS does not support this feature and uses a common underlying DB for multi-site mode,    Multi-tenant mode could be an extremely useful feature when you    would like to run multiple sites on same instance and scale out the database based on the db prefix
+2
Depends on the clustering support from underlying JEE engine.
CSR Module+2
Referred to as “Sales Center” is a Rich client    application for CSR
Sales center is a thick client application and needs to be installed on every CSR desktop, it uses the WCS back end shared by production environment.
+3v
Referred to as “Customer Service Cockpit” is a module to support call center operations like order management
+2
ATG provides Service module for service center agents. Commerce service center app uses it's own database which is different from production customer facing site DB.
Search Engine+2
WCS Search is based on SOLR search engine.


Does not really unleash all the power of SOLR and integration with any other search engine is not supported OOB
+3
SOLR search and native support for Endeca Integration
+2
ATG Search engine or Endeca
Print ModuleNot supportedHybris Print Module
PIM+2
Limited PIM features Supported by “Commerce Management Center” and Commerce Accelerator
+3
Support by Hybris PIM module. Much more advanced PIM support as compared to other 3 products, this is good enough for medium scale retailers

ATG does not support a native PIM module




Business User Tool+2

WCS support Commerce Management center which is supported on limited set of browsers, it is a Flash based user interface.
WCS supports authoring and production environment similar to ATG.
+3

Hybris supports product cockpit tool which allows business users to manage product and catalog information.
+3

Referred to as BCC (Business Control Center) is a web based business user interface.

ATG supports publishing and production server, publishing server is used by business users for content creation, aggregation and version management.



Data Access Layer
+3
EJB, BOD / DSL (Similar to Ibatis and Hybernate data access API)


EJB specification supported by WCS is quite outdated and BOD programming and WCS query language used in BOD is pretty complex to learn and implement.

But the good news is we have the flexibility to easily create custom tables and write custom optimized native SQL's as an alternate to EJB and DSL components
+1
In Hybris you have to stop thinking in terms of tables, DAO's make use of Hybris Type system for persistence and FlexibleSearch engine for executing query. It takes time to get into the weeds of these concepts and can be confusing as there is a complete shift from normal database table and native SQL concepts.


Personally I did not like the idea about inability to query database directly, I think this can be a big limitation for ongoing production support.
+1
ATG Data Anywhere architecture provides a “Repository API” abstraction on top of multiple datasources like RDBMS, LDAP or File system. This is another custom OR mapping style of data access which serves as an alternative to EJB or plain JDBC. ATG boosts RQL (Repository Query Laguage) for writing queries against unified repository. 

I just feel that it is easier to find good DBA's in the market to write optimized SQL compared to learning and writing another non stadard RQL language based queries.
OMS+3
WCS does not have any module for OMS, instead IBM sterling commerce is another IBM offering which integrates well with WCS to provide end to end OMS capabilities
+3
Hybris Order Management module can server as a full-fledged OMS
 +1

No native support for Order management system

Unit Testing
+1
WCS lacks a concrete unit testing framework, most of the components cannot be unit tested without the complex and heavy WCS runtime support.
+3
Hybris is leaps and bounds ahead of others in this category, it inherits all of the standard Spring unit testing support, there isn't a comparison to the extent a component can be unit tested independent of JEE    container in Spring.
 +1

Similar to WCS and lacks a native support for unit testing.
Deployment Suitability+3
Very Large retailers
+2
Mid-sized implementation
+2
Mid to Large size implementation
Community Adoption+2
Although commercial the documentation is very detailed and community driven, forums are not so active


Software is not free to download, you need a partner world account to get your hands on WCS even for development and evaluation purpose
+1
Closed community, I think this will only hurt its adoption, documentation is not so great.


For instance I can google on IBM infocenter pages, but finding something out of hybris is near impossible, you need to login to hybris wiki and search for the details.
+3
After Oracle acquisition the software is free to download for learning and evaluation purpose


Documentation is pretty detailed and well structured

http://edelivery.oracle.com

Starter Stores+3
WCS provides nearly a dozen of starter stores for B2B and B2C store models, I think this is a great asset and let's development teams to get started with a fully functional store in no time, of course you need to use it as a base to perform your customization.
+2

Hybris Accelerators can be used to create custom stater stores for b2b and b2c store model.


 +2

ATG provides starter stores that share a common master catalog and store assets similar to WCS extended sites model, it also provides starter stores for independent B2C and B2B stores.

Trends


+2
Holding Fort.


+3
Growing Strong


+2
Catching up

Explain use of ImageMagik in Hybris e-commerce multi-channel | Hybris tutorial

About ImageMagik

ImageMagick is an open source software suite for displaying, converting, and editing raster image files. It can read and write over 100 image file formats. ImageMagick is licensed under the Apache 2.0 license.
Use the convert program to convert between image formats as well as resize an image, blur, crop, despeckle, dither, draw on, flip, join, re-sample, and much more.
Eg. $magik>convert  hello.jpg hello.png
This command will convert file hello from jpg format to png format.
For more details on imageMagik refer to: http://www.imagemagick.org/script/index.php
We use convert.exe file to execute the conversion from a java path using Runtime.exe or ProcessBuilder:

1.Using Runtime :
 Process p = Runtime.getRuntime().exec("E:/ImageMagick-6.7.0-Q16/convert.exe E:/ImageMagick-6.7.0-Q16/logo.jpg E:/ImageMagick-6.7.0-Q16/logo.gif");

or

2.Using Processbuilder :
ProcessBuilder pb = new ProcessBuilder("E:/ImageMagick-6.7.0-Q16/convert.exe", "E:/ImageMagick-6.7.0-Q16/logo.jpg", "E:/ImageMagick-6.7.0-Q16/logo.gif");
Process start = pb.start();

Here , "E:/ImageMagick-6.7.0-Q16/' is the location of the ImageMagik directory.Location of images can be anything.




Steps to create webstore or online website using Hybris e-commerce multi-channel suite

If you are very new to Hybris e-commerce then follow below steps to create a own webstore or online website
1. Download any version of Hybris suite like Hybris 4.8
2. After download go to CMD and go to Installed directory
  like c:/hybris/bin/plateform
 
3. set ant
Hybris provides a full fledge running webstore through accelarator extension so we only need to create accelarator type own extension
and we can customized this accordingly our requirements
so for that we need to type
ant modulegen command
after hit enter it will create six extension in our custom folder
Now you can customized it accordingly
ownWebstorecockpits
ownWebstorecore
ownWebstorefacades
ownWebstoreinitialdata
ownWebstorestorefront
ownWebstoretest
in above extension all UI related file and controller will in ownWebstorestorefront
and your default webstore url will
http://localhost:9001/ownWebstorestorefront?site=electronic

How can implement Ehcache in Hybris multi-channel ecommerce suite ? step to implement Ehcache in Hybris

Hybris is provide caching in spilit of content called region and we can configure and add object in each region cache
In Hybris core-cache.xml is heart of caching configuration in Hybris
Suppose we need to implement a another cache region then you need to add below code in core extension spring xml file
<alias alias="cacheRegionsList" name="defaultScenarioCacheRegionList" />
  <bean name="ownProductCacheRegion" class="de.hybris.platform.regioncache.region.impl.EHCacheRegion">
     <constructor-arg name="name" value="ownCacheRegion" />
     <constructor-arg name="maxEntries" value="50000" />
     <constructor-arg name="evictionPolicy" value="LFU" />
     <property name="handledTypes">
         <array>
             <value>1</value>
         </array>
     </property>
  </bean>
 
  <bean id="defaultScenarioCacheRegionList" class="java.util.ArrayList">
                    <constructor-arg>
                        <list>
                             <ref bean="typesystemCacheRegion"/>
                            <ref bean="entityCacheRegion"/>
                            <ref bean="queryCacheRegion"/>
                             <ref bean="ownProductCacheRegion"/>
                        </list>
                    </constructor-arg>
   </bean>
  
  
  
   After add above code you need to access caching by using DefaultCacheController for we need to add below code to access them
  
   @Autowired
 CacheController controller;




 final Collection<CacheRegion> regions = controller.getRegions();
  for (final CacheRegion region : regions)
  {
   if (region.toString().equals("goodyearCacheRegion"))
   {
   
    final Collection<CacheKey> cacheKey = region.getAllKeys();
    for (final CacheKey cach : cacheKey)
    {
     System.out.println(" Cache Region name  " + region.getName() + " Cache key  " + cach.toString());
    
    }
    final CacheStatistics stats = region.getCacheRegionStatistics();
    stats.getHitCount();
    //    (...)
   }
  }

Explain Model in Hybris multi-channel suite ? Define Model in Hybris ?

Model are the way to represents item in Hybris ie. each of item is represented by in Model Class. So Model class is just like POJO class
which contain all item attributes
For every item type after build Hybris framework that create class with suffix Model and configuration file i.e. for product type item model class
will create with name ProductModel

Suppose you have define below item type in items.xml
<itemtype
  generate="true"
  code="ContactRequest"
  jaloclass="de.hybris.springmvcdemo.jalo.ContactRequest"
  extends="GenericItem"
  autocreate="true"
  >
    <attributes>
      <attribute qualifier="message" type="java.lang.String">
        <persistence type="property"/>
      </attribute>
    </attributes>
</itemtype>

Then generated model class will be

package de.hybris.springmvcdemo.model;

import de.hybris.platform.core.model.ItemModel;

/**
 * Generated Model class for type ContactRequest first defined at extension {literal}springmvcdemo{literal}
 */
@SuppressWarnings("all")
public class ContactRequestModel extends ItemModel
{
    /** <i>Generated type code constant.</i>*/
    public final static String _TYPECODE = "ContactRequest";
   
    /**
         * <i>Generated constant</i> - Attribute key of <code>ContactRequest.message</code> attribute defined
         * at extension <code>springmvcdemo</code>.
         */
    public static final String MESSAGE = "message";
   
   
    /** <i>Generated variable</i> - Variable of <code>ContactRequest.message</code> attribute defined
         * at extension <code>springmvcdemo</code>.
         */
    private String _message;
   
   
    /**
     * <i>Generated constructor</i> - for all mandatory attributes.
     * @deprecated Since 4.1.1 Please use the default constructor without parameters
     */
    @Deprecated
    public ContactRequestModel()
    {
        super();

    }
   
    /**
     * <i>Generated constructor</i> - for all mandatory and initial attributes.
     * @deprecated Since 4.1.1 Please use the default constructor without parameters
     * @param _owner initial attribute declared by type <code>Item</code> at extension <code>core</code>
     */
    @Deprecated
    public ContactRequestModel(final ItemModel _owner)
    {
        super(
            _owner
        );

    }
   
   
    /**
     * <i>Generated method</i> - Getter of the <code>ContactRequest.message</code> attribute defined
         * at extension <code>springmvcdemo</core>.
     * @return the message
     */
    public String getMessage()
    {
        if( !isAttributeLoaded(MESSAGE))
        {
          this._message = getAttributeProvider() == null ? null : (String) getAttributeProvider().getAttribute(MESSAGE);
          getValueHistory().loadOriginalValue(MESSAGE, this._message);
        }
        throwLoadingError(MESSAGE);
        return this._message;
    }
   
    /**
     * <i>Generated method</i> - Setter of <code>ContactRequest.message</code> attribute defined
         * at extension <code>springmvcdemo</code>.
     *
     * @param value the message
     */
    public void setMessage(final String value)
    {
        this._message = value;
        markDirty(MESSAGE);
    }
   
}

Explain Service layer in Hybris multi-channel Suite? what is service layer ?


Service layer is interface implemented class which is abstract from persistence layer which contain function logic and no-persistence related code
So when you writing any service layer make sure that it should loosely coupled with persistence layer as possible .
Hybris multichannel suite expose all functionality in ther form of service
1. Bussiness Service- service such as cart handling , Back order etc
2. Infrastructure service  - service such as internationalization, export service, import service
3. System service - such as model handling , session handling.

Service layer has interacted with persistence layer via DAO layer and the through using Model it has interacted with service layer and DAO has interacted with
persistence layer through Flexible search and SQL statement.

Gift Card and Voucher Changes in Hybris Multi-channel suite 4.8 Accelerator | Hybris 4.8 tutorial

Gift Card /Voucher Changes in Hybris Accelerator:
1.    Voucher Façade creation
•    Defining Voucher interface: Voucher interface has been defined comprising following methods
a) String redeemVoucher(String voucherCode)

b) Boolean checkVoucherCode(String voucherCode)
•    Implementing Voucher methods: Voucher methods have been implemented using CartVoucherFacadeImpl class. RedeemVoucher methods redeems voucher for given voucher code & checkvoucherCode methods check for the validity of the voucher code.
•    Spring configuration for VoucherFacade: below is the spring configuration for voucherFacade
    <!-- Added by for Voucher(Gift card) changes -->
    <bean id="cartVoucherFacade" class="se.KM.facades.voucher.impl.CartVoucherFacadeImpl" scope="tenant"/>
   
2.    Store pickup changes: Following classes have been create/updated for store pickup
a.    KMUserFacade
b.    KMAddressService
c.    KMAddressServiceImpl
d.    KMAddressDao
e.    KMAddressDaoImpl
f.    KMCustomerReviewDaoImpl
g.    MultiStepCheckoutController
h.    GiftVoucherValidator
i.    deliveryAddressDetails.tag
j.    deliveryAddressSelector.tag
k.    header.tag
l.    deliveryAddressDetails.tag
m.    deliveryAddressSelector.tag
n.    /KMstorestorefront/web/webroot/WEB-INF/tags/mobile/common/header/header.tag

•    Spring configuration for store pickup: below are the spring file changes in file KMstorecore-spring-integration.xml
    <!-- Changes done By Sachin  -->
    <!--H&M Address Service -->
    <bean id="KMAddressService" class="se.KM.core.servicelayer.user.impl.KMAddressServiceImpl" parent="abstractBusinessService" scope="tenant">
        <property name="addressDao" ref="addressDao"/>       
    </bean>
   
    <!--H&M Address DAO -->
    <alias alias="addressDao" name="KMAddressDaoImpl"/>   
    <bean id="KMAddressDaoImpl" class="se.KM.core.servicelayer.user.daos.impl.KMAddressDaoImpl" scope="tenant"/>
   
    <!--H&M Checkout Facade -->
    <!-- <alias alias="checkoutFacade" name="KMCheckoutFacade"/>
    <bean id="KMCheckoutFacade" class="se.KM.core.commercefacades.order.impl.KMCheckoutFacade" scope="tenant" parent="defaultCheckoutFacade">
        <property name="KMAddressService" ref="KMAddressService"/>
    </bean> -->
   
    <!--H&M User Facade -->
    <alias alias="userFacade" name="KMUserFacade"/>
    <bean id="KMUserFacade" class="se.KM.core.commercefacades.user.impl.KMUserFacade" scope="tenant" parent="defaultUserFacade">
        <property name="KMAddressService" ref="KMAddressService" />
    </bean>
    <!-- H&M customer review DAO- Added by SACHIN -->
    <alias alias="customerReviewDao" name="KMCustomerReviewDao"/>
    <bean id="KMCustomerReviewDao" class="se.KM.core.servicelayer.user.daos.impl.KMCustomerReviewDaoImpl" parent="defaultCustomerReviewDao" scope="tenant"/>


3.    Promotion “KM Buy X get A% discount on X” changes: Following changes have been made while defining this promotion
•    Creating Promotion:  changes have been made in /KMstorecore/resources/KMstorecore-items.xml file
            <itemtype code="KMProductBOGOFPromotion"
                extends="ProductBOGOFPromotion"
                jaloclass="se.KM.core.promotions.jalo.KMProductBOGOFPromotion"
                autocreate="true"
                generate="true" >
                <attributes>
                    <attribute
                        qualifier="percentageDiscount"
                        autocreate="true"
                        type="java.lang.Double">
                        <defaultvalue>Double.valueOf(0.0D)</defaultvalue>
                        <description>Discount on product Y</description>
                        <modifiers read="true" write="true" />
                        <persistence type="property"/>
                    </attribute>
                </attributes>
            </itemtype>
•    KMc changes: following changes have been made in KMc.xml file for front end
    <!-- Configuration for extension KMstorecore -->
    <type name="KMProductBOGOFPromotion" mode="append">
        <organizer>
            <editor mode="append">
                <tab name="tab.promotion.properties" mode="append">
                    <section name="section.promotion.products" mode="append">
                        <columnlayout leftwidth="370">
                            <row>
                                <attribute name="percentageDiscount" labelwidth="100" />
                                <text name="text.KMproductbogofpromotion.percentageDiscount" />
                            </row>
                        </columnlayout>
                    </section>
                </tab>
            </editor>
        </organizer>
    </type>
•    Changes in Jalo class: following changes have been made in jalo class in order to invoke custom evaluate method
/KMstorecore/src/se/KM/core/promotions/jalo/KMProductBOGOFPromotion.java
Following methods need to be override while defining a new promotion
    @Override
    public List<PromotionResult> evaluate(final SessionContext ctx, final PromotionEvaluationContext promoContext)
    @Override
    public String getResultDescription(final SessionContext ctx, final PromotionResult promotionResult, final Locale locale)