View source | Discuss this page | Page history | Printable version   

How to add an algorithm to level pricing infrastructure



As explained in the module documentation, level pricing infrastructure needs algorithms in order to work. These algorithms indicates which way will be followed to set prices. These prices are set based on the information stored in the level pricing infrastructure. Normally, each algorithm will correspond with a module which will contain the algorithm for ERP and (optionally) for Openbravo Web POS.

Module dependencies

If your algorithm will be used just in the ERP side (sales order window) the module will depend on Level pricing infrastructure module. However if your module will work also in Openbravo Web POS, it will depend on Retail level pricing module. It happens because is needed to move level pricing information to Web POS side.

In this how to we are going to implement an algorithm to be used in Openbravo ERP and in Openbravo Web POS, so it will depend on Retail level pricing module.

Step 1: Create the module to store the algorithm

View larger
View larger
View larger

Step 2: Register the algorithm into the list of available algorithms

View larger

Step 3: Configure a product to use the new algorithm

View larger

Step 4: Develop the algorithm for ERP Side

To develop the algorithm for ERP we will take advantage of the hook called "OrderLineQtyChangedHook". This hook is executed when some events happens in an order line.

In the implementation we should select the price and then return it to the main flow.

package org.openbravo.pricing.averagelevelpricing.hooks;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import javax.enterprise.context.ApplicationScoped;
import org.hibernate.criterion.Restrictions;
import org.openbravo.common.hooks.OrderLineQtyChangedHook;
import org.openbravo.common.hooks.OrderLineQtyChangedHookObject;
public class OrderLineQtyChangedHookImplementation implements OrderLineQtyChangedHook {
  public void exec(OrderLineQtyChangedHookObject hookObj) throws Exception {
    BigDecimal newPrice = null;
    //Check if the changed field is the quantity
    if (hookObj.getChanged().equals("inpqtyordered")) {
      //Here goes the code to select the price
      newPrice =BigDecimal.TEN;
      //The new price is returned through hookObj 
      if (newPrice != null) {
        hookObj.setPrice(newPrice.equals("") ? BigDecimal.ZERO : newPrice.setScale(
            hookObj.getPricePrecision(), BigDecimal.ROUND_HALF_UP));
      } else {

Step 5: Develop the algorithm for Openbravo Web POS

Create a component provider to serve JS files

We need a server side component to serve our JS files to Openbravo Web POS. This component is called component provider.

package org.openbravo.pricing.averagelevelpricing;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.enterprise.context.ApplicationScoped;
import org.openbravo.client.kernel.BaseComponentProvider;
import org.openbravo.client.kernel.BaseComponentProvider.ComponentResource.ComponentResourceType;
import org.openbravo.client.kernel.Component;
import org.openbravo.client.kernel.ComponentProvider;
import org.openbravo.retail.posterminal.POSUtils;
 * @author guilleaer
public class SLP_ComponentProvider extends BaseComponentProvider {
  public static final String QUALIFIER = "AVLP_Main";
  public static final String MODULE_JAVA_PACKAGE = "org.openbravo.pricing.averagelevelpricing";
  public Component getComponent(String componentId, Map<String, Object> parameters) {
    throw new IllegalArgumentException("Component id " + componentId + " not supported.");
  public List<ComponentResource> getGlobalComponentResources() {
    final List<ComponentResource> globalResources = new ArrayList<ComponentResource>();
    final String prefix = "web/" + MODULE_JAVA_PACKAGE + "/js/";
    String[] resourceList = { "addalgorithm" };
    for (String resource : resourceList) {
      globalResources.add(createComponentResource(ComponentResourceType.Static, prefix + resource
          + ".js", POSUtils.APP_NAME));
    return globalResources;

Create the algorithm

Finally we are going to develop the algorithm in the client side. To do it we will use:

See comments in the source code to understand what is happening

//Add a properrty to indicate that a module is available
  properties: ['AVLP_algorithm'],
  loadFunction: function (terminalModel) {
    var algorithms = terminalModel.get('pricingAlgorithms');
    if (!algorithms) {
      algorithms = {};
    algorithms['AVLP_algorithm'] = true;
    //Register the algorithm in the hook
    OB.MobileApp.model.hookManager.registerHook('LVLPR_addProduct', function (args, callbacks) {
      var linesToModify = [];
      var affectedLines = args.receipt.getLinesByProduct(;
      if (args.algorithm === 'AVLP_algorithm' && args.originalArgs.productToAdd.get('groupProduct') && affectedLines && affectedLines.length > 0) {
        var memo = 0;
        var totalQty = 0;
        //Get total qty
        totalQty = _.reduce(affectedLines, function (memo, line) {
          return memo + line.get('qty');
        }, memo);
        //Add to the total qty the qty of the new product
        if (_.isNaN(args.originalArgs.qtyToAdd) || _.isUndefined(args.originalArgs.qtyToAdd) || _.isNull(args.originalArgs.qtyToAdd)) {
          totalQty += 1;
        } else {
          totalQty += args.originalArgs.qtyToAdd;
        //If lines which exists in the ticket are modified
        if (linesToModify.length > 0) {
//          linesToModify.push({
//            lineCid: line.cid,
//            newQty: totalQty,
//            newPrice: finalResult.price,
//            productProperties: [{
//              name: 'AVLP_usedRange',
//              value: finalResult.minQtyToUse
//            }],
//            lineProperties: []
//          });
          args.originalArgs.linesToModify = linesToModify;
          //Use lines to modify
          args.originalArgs.useLines = true;
        } else {
          //Use the product
          args.originalArgs.productToAdd.set('standardPrice', 10);
          args.originalArgs.useLines = false;
      } else {
        //Don't do nothing
        args.originalArgs.useLines = false;
      OB.MobileApp.model.hookManager.callbackExecutor(args.originalArgs, callbacks);
    terminalModel.set('pricingAlgorithms', algorithms);

Retrieved from ""

This page has been accessed 3,941 times. This page was last modified on 29 October 2013, at 08:04. Content is available under Creative Commons Attribution-ShareAlike 2.5 Spain License.