As part of the project to share more of our code, last month saw the release of the Price Modification module. This post will present this module and explain a little how it works.
A normal coreBOS obtains the product and service price from the unit price field on the product or service. For example, when we are creating a quote and select a product on any line, the price that is filled in is a copy of the value in the unit price field of the selected product at that moment.
This behavior is rather limited as we cannot set a different price depending on many of the possible reasons we may have to do so like, the selected account, or the geographic zone that the account belongs to, the number of units purchased or simply some promotion the product may be on today.
The purpose of the Price Modification module is to permit us to define a very flexible and powerful pricing system. The module is a complex rule escalation system that permits us to define a price/discount or a cost/margin value to be used as the line unit price of the selected product.
The Module
The Price Modification module has five fields that define the rule to be applied and four related lists with Accounts, Contacts, Products, and Services that define which records are affected by the rule.
Each record in the module defines an individual price modification rule that will be applied if it passes all the conditions evaluated during the escalation search process. The first record found that passes all the conditions will be used to return the modified price.
The five fields are grouped into three sets:
1.- how to apply
2.- what to return
The Return Type picklist permits us to indicate if we want to have the price modified in one of two possible ways:
3.- Value to use
The value of the record can be obtained in one of two ways
As an example, while I was testing I created and selected this map:
<map>
<expression>if $bill_country == 'Spain' then 10 else 20 end</expression>
</map>
which applies a 10% discount or margin to all Accounts whose billing country is Spain and a 20% discount to all other countries.
The Search Process
The search process follows these steps.
In lay-mans terms that would be something like, search for the category of the product and a client, if you can't find it, search for the category of the product with no client selected (so it is a global discount on the category), if not found, search for a record with the related product and client (a discount for that product to that client), then search for a record related only to the client (a global discount for that client), now search for a record related only to the product (a global discount on the product) and finally a record not related to anything (a default value).
If a record is found, the value will be obtained and the return type selected will be applied. If no record is found the normal unit price field and a discount of 0 will be returned (the current default behavior).
Additional Information
You can download the module from its' home in github
The module can be activated or deactivated in Settings > Module Manager > Module Status
There is a hidden and rudimentary test file you can use to evaluate the search results of your current configuration: TestPrice.php
For this to work we introduced a new event in coreBOS: corebos.filter.inventory.getprice, which means that you will need an up to date coreBOS and also that anyone can now create a module or extension that implements any type of logic to retrieve the price and discount of the product.
Closing Comments
The Decision Table Business Map is powerful enough to do all the above escalation by itself and even implement a much more complex (or simpler) rule system. So we could have implemented a simple change in coreBOS to detect a specifically named Decision Map and use it to obtain the price (like we do with many other business maps) but there were some significant conditions that made us take the Price Modification module path which I would like to share with you and leave here for future reference.
The incredible (and hidden) power of the coreBOS ecosystem.