Development Environment

Extending Openbravo Web POS through Client Side Hooks

In this post we will talk about on of the improvements included in Openbravo web POS – RMP26 called Client Side Hooks which allow developers to extend the Openbravo Web POS solution in a modular and an easy maintainable way.

What are Client Side Hooks?

Client Side Hooks provide an easy mechanism to extend functionality with external modules. It basically consists on a lightweight way to include dependencies from third party modules.

Hooks are created in some specifics points of Openbravo web POS (here you can find information about the available hooks) and the modules just need to register into this hook to take advantage of it.

The image shows How Openbravo Web POS Hooks work.

Some useful examples

  • My module must prevent products from being added to the order when their price is lower than 1€.

    • This hook (OBPOS_PreAddProductToOrder) will solve your problem because on it you will receive the product which is being added and you can cancel this add operation using a specific parameter.

  • When a ticket is deleted (without having been completed yet) I want to save this event information in the backend.

    • This hook (OBPOS_PreDeleteCurrentOrder) will solve your problem. You can execute an asynchronous call to the backend with some details of the deleted order.

  • Based on the final amount of the ticket, I want to mark the order with an specific category.

    • This hook (OBPOS_PreDeleteCurrentOrder) will allow you to analyze the order details and save some specific data into it. This information will be sent later to the backend, where the order loading process will automatically save it.

Do you need a new Hook?

Usually developers will use those hooks that are included in Openbravo Web POS, but in some circumstances a developer may require new ones to develop an specific functionality. In this case, we recommend the developer to add by itself the hook and then develop the solution based on it. Also, he should communicate to Openbravo support team that this hook is needed. The team will evaluate the hook and if they think it make sense, it will be properly documented and included in the next RMP.  Following this process, the new development will run without patches once the hook is published.

How to register a function into a Hook?

The code below shows the way to register a function into a specific hook. This function will be executed when the flow of the main program reaches the hook. At this moment, hooks mechanism will call sequentially to each registered function. Once the callback is performed by the last executed function, the flow will continue taking into account the new values of the arguments.

1
2
3
4
5
6
OB.MobileApp.model.hookManager.registerHook('BASMOD_HookName', function (args, callbacks) { 
  // execute all your logic here // If your code generates any kind of asynchrony, remember to execute 
  // callbackExecutor when the response is received. 
  // This is a MUST to properly manage callbacks 
  OB.MobileApp.model.hookManager.callbackExecutor(args, callbacks); 
});

Producing different behaviors on the original program flow

Parameters received by functions registered in a specified hook can be modified by the hook. This can be used, as an example, to add information to the current order. Moreover, by including a specific property into the arguments (returned later through callbackexecutor) we can change the behavior of the main flow (i.e. Cancel the addition of a product to the ticket). This should be well documented for every hook.

How to manage asynchrony in a Hook?

Hooks allow developers to register functions which contains asynchronous calls, but in these cases each function must indicate to the hook that all the asynchronous tasks are finished (calling to callbackexecutor), this means that each function is responsible to manage the asynchrony that it generates.

A Client Side Hooks example

To end this post I will show you an example. I’m going to check the stock of the product which is being added to the ticket calling to backend. If the backend response says that the stock is not enough I will show an error and the product will not be added to the ticket.

(Note:  If you are interested in this functionality, a module is available for Openbravo Web POS, called Stock Validation)

Step 1 – Create a module dependant on Openbravo Web POS with a JS file

We will skip this part because this is not the purpose of this post. However,  here you can check how to create a module which adds a js file to Openbravo Web POS.

Step 2 – Create a json process simple

This process will check if the product is available. In this example, the servlet always will answer false (not enough stock);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.openbravo.retail.samplemodule;
 
 
import javax.servlet.ServletException;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.openbravo.retail.posterminal.JSONProcessSimple;
 
public class StockChecker extends JSONProcessSimple {
 
@Override
 
public JSONObject exec(JSONObject jsonData) throws JSONException, ServletException {
  // here we should check the stock
  JSONObject preFinalResult = new JSONObject();
  preFinalResult.put("allowSell", false);
  JSONObject finalResult = new JSONObject();
  finalResult.put("data", preFinalResult);
  finalResult.put("status", 0);
  return finalResult;
}
 
}

Step 3 – Register our function in the selected hook (OBPOS_PreAddProductToOrder)

In this example our function introduces an asynchronous operation (call to server to check the stock). So we will call to executeCallback in the callback of the asynchronous operation.

To let  the system know that we want to cancel the operation, we will add a property to the arguments (cancelOperation). The way we know it is because it’s explained in the documentation of this hook.

Finally, to demonstrate how we can modify values of the received parameters, we will add a ‘X’ to the product name to warn us about the stock check was not done.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
OB.MobileApp.model.hookManager.registerHook('OBPOS_PreAddProductToOrder', function (args, c) {
 
//create a function to call to the server
function executeCallToServer() {
 
  var serverCall = new OB.DS.Process('org.openbravo.retail.samplemodule.StockChecker');
 
  OB.UTIL.showLoading(true);
 
  serverCall.exec({
    orderLine: args.productToAdd,
    qtyToAdd: args.qtyToAdd
  }, function (data, message) {
    OB.UTIL.showLoading(false);
    if (data.allowSell === false) {
      //Cancel the operation. The product will not be added;
      args.cancelOperation = true;
      OB.UTIL.showConfirmation.display('Product is not available', 'The stock of this product is not enough.');
    }
    OB.MobileApp.model.hookManager.callbackExecutor(args, c);
  }, function (error) {
    OB.UTIL.showLoading(false);
    console.log('An error happened while checking stock');
   //Here also we are able to change the name of the product
    args.productToAdd.set('_identifier', args.productToAdd.get('_identifier') + ' - X');
    //add the product normally
    OB.MobileApp.model.hookManager.callbackExecutor(args, c);
  });
 
}
 
//call to function
console.log('Hook executed', args);
executeCallToServer();
});

Here you can find a .zip which contains the module of this example

Final result

In this video you can see how this example works.

Useful links

Previous post

Openbravo 3 Brand New Features

Next post

Openbravo new product vision and roadmap are here!

No Comment

Leave a reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>