Projects:New Discounts Engine/Specs
![]() | Back to Projects:New_Discounts_Engine |
Contents |
Goal
The main objectives of this project are:
- Create a web service that given a ticket, returns its applicable discounts.
- To provide an infrastructure that allows to build and run a new synchronous discounts engine that will be used by the web service to generate the results.
Functional Requirements
Current State
Currently we have two different implementations for calculating discounts:
- Backend: the discount calculation is based on PL/SQL implementation of the discount rules. The main disadvantage of this implementation is that it needs the ticket (order) to be already persisted in database to execute the discount calculation logic.
- WebPOS: has its own discounts calculation engine. One of the main disadvantages of this engine is that the calculation is asynchronous as it needs to query the local database to extract the information of the different discount rules.
Desired Implementation
The expected requirements for the new discounts engine are:
- It should work synchronously
- Based on new Javascript technologies
- Capable of working completely independent from the WebPOS, in order to be used also by other applications and components. This way it will allow to have a common engine for the discount calculation both in the backend and in WebPOS.
To allow external applications use this new discounts engine, a new web service will be developed.
Technical Specs
A Common Engine
One of the main requirements of this project is to ensure that we provide a discounts engine that is not only used in WebPOS but it can reused by different application components, including those which are part of the backend.
The new discounts engine is going to be developed using Javascript, for this reason we should provide a mechanism to execute it in the backend. In an initial stage of research, several Javascript engines for the JVM were considered:
After evaluating the different alternatives, GraalJS was the option finally taken.
To integrate GraalJS in Openbravo, we are not going to directly use the GraalVM but the Graal SDK libraries will be deployed on top of the OpenJDK instead:
Discount Executor
This project will introduce the concept of DiscountExecutor, a component that will allow to define implementations for calculating discounts. It will be the central part of an infrastructure depicted below:
The components of this infrastructure are:
- DiscountExecutor: an interface that should be implemented to provide the discount calculation logic.
- DiscountJSExecutor: a DiscountExecutor that implements the discount calculation logic using the Javascript language. It is an abstract class that should be extended implementing the discount calculation logic and selecting the Javascript engine to execute that logic.
- GraalDiscountsExecutor: a DiscountJSExecutor that calculates the discounts using GraalJS engine and the new discounts engine. This is the component that will be used by the discounts web service.
- DiscountsComponent: a component that extends StaticResourceComponent to generate the static Javascript resources required to execute the new discounts engine in the backend.
- DiscountDataHookSelector: a class that allows the DiscountJSExecutor to select hooks that allows to add additional information to the discount rules definition before sending them to the new discounts engine.
Discounts Web Service
The new discounts web service will implement the following flow:
- Retrieve the ticket from the HTTP request
- Retrieve the applicable discounts rules for the ticket from database
- Execute the new discount engine through the GraalJS discount executor mentioned in the previous section.
- Return the calculation result
Ticket API
A new API is going to be provided as an effort to try to standardize the definition on a ticket. This is the minimum properties that are required to define a POS ticket.
This API would be used and extended by different kind of web services (Discounts, OMS, Loyalty...). Thus, all of them will be using a common definition both on their input and output.
The base API definition can be found here.
API Specification
It will also be developed a mechanism that will allow to specify the API of the exposed web services in Openbravo. And we will make use of it to document the discounts web service.
After a research, OpenAPI is the selected approach to create this API documentation mechanism. Its main advantages are:
- It is heavily used
- Great community of users
- Support for different languages (including Java, of course)
Testing Infrastructure
A new testing infrastructure is going to provided, with several features:
- A model that will allow to define tickets, discount rules and discount scenarios.
- Matchers for the testing model. They will allow to:
- Make tests more readable
- Allow non-technical people to define the test cases at a high level.
- An standalone service based in node, that will provide:
- The ability to deploy and execute the discounts engine. Moreover, it will allow to deploy different applications(sources).
- The ability to run the tests, allowing to skip the DAL initialization part once the code is already deployed. This will allow to execute the tests in faster way.
- The ability to run in a debug mode, that will allow to debug the code by using the web browser code inspector.
- Three different test execution modes to calculate the discounts:
- Graal: directly using the GraalJS engine
- WebService: using the Discounts Web Service
- Remote: through the node service mentioned above.
Module Structure
The components of this project have been divided into different modules, as many of them can be reused also by other modules. The structure is form as follows:
- Retail Discouns (org.openbravo.retail.discounts): contains both the new and old discounts engines and the implementation of the rules that belong to the retail pack.
- Discounts Engine For Backend (org.openbravo.discounts): contains the DiscountExecutor infrastructure and the discounts web service .
- Ticket API (org.openbravo.api.ticket): keeps the definition of the Ticket API.
- JS Executor (org.openbravo.service.jsexecutor): the Graal libraries are placed in this module. It is also the module that has the node test service.
- Open API (org.openbravo.service.openapi): a module that looks for OpenAPI definitions in other modules and deploys them to be displayed with Swagger UI. Used to document the discounts web service. Note that it is not required to have any dependency with this module.
Future Work
After this project, the following topics will be opened for a future implementation:
- Merge the discounts engine in core, including the integration with GraalJS and the testing infrastructure.
- Replace the existing PL implementation of the discounts rules in the backend with implementations based in the new discounts engine.