RATE_CACHER Module
     __________________________________________________________

   Table of Contents

   1. Admin Guide

        1.1. Overview
        1.2. Dependencies

              1.2.1. OpenSIPS Modules
              1.2.2. External Libraries or Applications

        1.3. Exported Parameters

              1.3.1. vendors_db_url (str)
              1.3.2. vendors_db_table (str)
              1.3.3. vendors_hash_size (int)
              1.3.4. clients_db_url (str)
              1.3.5. clients_db_table (str)
              1.3.6. clients_hash_size (int)
              1.3.7. rates_db_url (str)
              1.3.8. rates_db_table (str)

        1.4. Exported Functions

              1.4.1.
                      get_client_price(client_id,is_wholesale,dialle
                      d_no,prefix_pvar,destination_pvar,price_pvar
                      ,minimum_pvar,increment_pvar)

              1.4.2.
                      get_vendor_price(vendor_id,dialled_no,prefix_p
                      var,destination_pvar,price_pvar,minimum_pvar
                      ,increment_pvar)

              1.4.3.
                      cost_based_filtering(client_id,is_wholesale,ve
                      ndors_csv,dialled_no,desired_margin,out_vend
                      or_csv)

              1.4.4.
                      cost_based_ordering(client_id,is_wholesale,ven
                      dors_csv,dialled_no,desired_margin,out_vendo
                      r_csv)

        1.5. Exported MI Functions

              1.5.1. rc_addVendor
              1.5.2. rc_deleteVendor
              1.5.3. rc_reloadVendorRate
              1.5.4. rc_deleteVendorRate
              1.5.5. rc_getVendorPrice
              1.5.6. rc_addClient
              1.5.7. rc_deleteClient
              1.5.8. rc_reloadClientRate
              1.5.9. rc_deleteClientRate
              1.5.10. rc_getClientPrice

   2. Contributors

        2.1. By Commit Statistics
        2.2. By Commit Activity

   3. Documentation

        3.1. Contributors

   List of Tables

   2.1. Top contributors by DevScore^(1), authored commits^(2) and
          lines added/removed^(3)

   2.2. Most recently active contributors^(1) to this module

   List of Examples

   1.1. Setting the vendors_db_url parameter
   1.2. Setting the vendors_db_table parameter
   1.3. Setting the vendors_hash_size parameter
   1.4. Setting the clients_db_url parameter
   1.5. Setting the clients_db_table parameter
   1.6. Setting the vendors_hash_size parameter
   1.7. Setting the rates_db_url parameter
   1.8. Setting the rates_db_table parameter
   1.9. get_client_price usage
   1.10. get_vendor_price usage
   1.11. cost_based_filtering usage
   1.12. cost_based_ordering usage

Chapter 1. Admin Guide

1.1. Overview

   The rate_cacher module provides a means of caching and
   real-time querying of the ratesheets assigned to your clients
   and / or vendors. It also allows for real-time cost-based
   routing and cost-based filtering.

1.2. Dependencies

1.2.1. OpenSIPS Modules

   The following modules must be loaded before this module:
     * No dependencies on other OpenSIPS modules..

1.2.2. External Libraries or Applications

   The following libraries or applications must be installed
   before running OpenSIPS with this module loaded:
     * None.

1.3. Exported Parameters

1.3.1. vendors_db_url (str)

   The DB URL for querying the Vendors used by the module

   Default value is “NULL”.

   Example 1.1. Setting the vendors_db_url parameter
...
modparam("rate_cacher", "vendors_db_url", "mysql://opensips:opensipsrw@l
ocalhost/opensips")
...

1.3.2. vendors_db_table (str)

   The DB Table for querying the Vendors used by the module

   Default value is “rc_vendors”.

   Example 1.2. Setting the vendors_db_table parameter
...
modparam("rate_cacher", "vendors_db_table", "my_vendors_view")
...

1.3.3. vendors_hash_size (int)

   The size of the hash table internally used to keep the vendors.
   A larger table is much faster but consumes more memory. The
   hash size must be a power of 2 number.

   Default value is “256”.

   Example 1.3. Setting the vendors_hash_size parameter
...
modparam("rate_cacher", "vendors_hash_size", 1024)
...

1.3.4. clients_db_url (str)

   The DB URL for querying the Clients used by the module

   Default value is “NULL”.

   Example 1.4. Setting the clients_db_url parameter
...
modparam("rate_cacher", "clients_db_url", "mysql://opensips:opensipsrw@l
ocalhost/opensips")
...

1.3.5. clients_db_table (str)

   The DB Table for querying the Clients used by the module

   Default value is “rc_clients”.

   Example 1.5. Setting the clients_db_table parameter
...
modparam("rate_cacher", "clients_db_table", "my_clients_view")
...

1.3.6. clients_hash_size (int)

   The size of the hash table internally used to keep the clients.
   A larger table is much faster but consumes more memory. The
   hash size must be a power of 2 number.

   Default value is “256”.

   Example 1.6. Setting the vendors_hash_size parameter
...
modparam("rate_cacher", "clients_hash_size", 1024)
...

1.3.7. rates_db_url (str)

   The DB URL for querying the Ratesheets used by the module

   Default value is “NULL”.

   Example 1.7. Setting the rates_db_url parameter
...
modparam("rate_cacher", "rates_db_url", "mysql://opensips:opensipsrw@loc
alhost/opensips")
...

1.3.8. rates_db_table (str)

   The DB Table for querying the Ratesheets used by the module

   Default value is “rc_ratesheets”.

   Example 1.8. Setting the rates_db_table parameter
...
modparam("rate_cacher", "rates_db_table", "my_clients_view")
...

1.4. Exported Functions

1.4.1.
get_client_price(client_id,is_wholesale,dialled_no,prefix_pvar,destin
ation_pvar,price_pvar,minimum_pvar,increment_pvar)

   For a call originating from the provided Client ID, on a
   wholesale or retail quality, going to dialled_no, the function
   will matched the dialled number against the client's ratesheet
   and return the matched prefix, destination, price, minimum and
   increment.

   The client_id pseudo-var will hold the client_id originating
   this call

   The is_wholesale pseudo-var will contain either a 1 or a 0,
   depending on whether the call is wholesale or retail ( see
   client ratesheet provisioning ).

   The dialled_no pseudo-var contains the DNIS - the dialled
   number for the current call. It needs to be in E164 format,
   without the leading +

   The prefix pseudo-var will contain the matched prefix from the
   client's ratesheet

   The destination pseudo-var will contain the matched destination
   from the client's ratesheet

   The price pseudo-var will contain the matched price from the
   client's ratesheet

   The minimum pseudo-var will contain the matched minimum from
   the client's ratesheet

   The increment pseudo-var will contain the matched increment
   from the client's ratesheet

   Possible parameter types
     * ALL Parameters - String/Integer or pseudo-variables

   This function can be used from any route.

   Example 1.9. get_client_price usage
...
if (get_client_price("my_client",1,"4072794242",$var(prefix),$var(dest),
$var(price),$var(min),$var(inc))) {
                        xlog("We matched $var(prefix) , $var(dest) , $va
r(price) , $var(min) , $var(inc) for the client's ratesheet\n");
                }

...

1.4.2.
get_vendor_price(vendor_id,dialled_no,prefix_pvar,destination_pvar,pr
ice_pvar,minimum_pvar,increment_pvar)

   For a call originating going to the provided vendor ID, going
   to dialled_no, the function will matched the dialled number
   against the vendor's ratesheet and return the matched prefix,
   destination, price, minimum and increment.

   The vendor_id pseudo-var will hold the vendor_id

   The dialled_no pseudo-var contains the DNIS - the dialled
   number for the current call. It needs to be in E164 format,
   without the leading +

   The prefix pseudo-var will contain the matched prefix from the
   vendor's ratesheet

   The destination pseudo-var will contain the matched destination
   from the vendor's ratesheet

   The price pseudo-var will contain the matched price from the
   vendor's ratesheet

   The minimum pseudo-var will contain the matched minimum from
   the vendor's ratesheet

   The increment pseudo-var will contain the matched increment
   from the vendor's ratesheet

   Possible parameter types
     * ALL Parameters - String/Integer or pseudo-variables

   This function can be used from any route.

   Example 1.10. get_vendor_price usage
...
if (get_vendor_price("my_vendor","4072794242",$var(prefix),$var(dest),$v
ar(price),$var(min),$var(inc))) {
                        xlog("We matched $var(prefix) , $var(dest) , $va
r(price) , $var(min) , $var(inc) for the vendor's ratesheet\n");
                }

...

1.4.3.
cost_based_filtering(client_id,is_wholesale,vendors_csv,dialled_no,de
sired_margin,out_vendor_csv)

   For a call originating from the provided Client ID, on a
   wholesale or retail quality, going to dialled_no, the function
   removes the Vendors ( from the vendor_csv list ) which do not
   pass the desired_margin condition, and sets the out_vendor_csv
   variable to the list of Vendor that meet the margin condition,
   while maintaining the initial order provided in the vendor_csv
   variable.

   The client_id pseudo-var will hold the client_id originating
   this call

   The is_wholesale pseudo-var will contain either a 1 or a 0,
   depending on whether the call is wholesale or retail ( see
   client ratesheet provisioning ).

   The vendors_csv pseudo-var contains a list of Vendors that need
   to be filtered based on the desired margin ( keep just those
   that match your desired percentage margin for this call )

   The dialled_no pseudo-var contains the DNIS - the dialled
   number for the current call. It needs to be in E164 format,
   without the leading +

   The desired_margin pseudo-var contains the minimum Integer
   margin that the script writer wants to achieve, based on the
   Client sell and Vendor buy prices. The formula used is :
   vendor_margin=(client_price - results[i])*100/client_price) .
   If the vendor_margin is higher than the desired_margin, then
   the Vendor is ok to use. The desired margin can be positive (
   call will be profitable ) or negative ( the call will cause a
   loss ).

   The out_vendors_csv pseudo-var is an output parameter, and the
   pvar will get populated with the CSV list of Vendors that meet
   the desired margin condition

   Possible parameter types
     * ALL Parameters - String/Integer or pseudo-variables

   This function can be used from a REQUEST or FAILURE route.

   Example 1.11. cost_based_filtering usage
...


# If we get a call from testClient on it's wholesale quality,
# going to number 40720018124, and we have to pick from the list
# of vendors 'testVendor,testVendor2' based on a a profit margin
# of 0 ( we do not want to lose money on this call ),
# then $avp(out_vendor_csv) will have the vendors that we need
# to use based on the above call characteristics, the order of the
# vendors that was provided in $avp(carrierlist) and the desired margin
$avp(client_id)="testClient";
$avp(is_ws)=1;
$avp(carrierlist)="testVendor,testVendor2";
$avp(dnis)="40720018124";
$avp(profit_margin)=0;

if (cost_based_filtering("$avp(client_id)","$avp(is_ws)","$avp(carrierli
st)","$avp(dnis)","$avp(profit_margin)","$avp(out_vendor_result)")) {
        xlog("XXX - Out of the $avp(carrierlist) carriers, we should onl
y use $avp(out_vendor_result) \n");
...

1.4.4.
cost_based_ordering(client_id,is_wholesale,vendors_csv,dialled_no,des
ired_margin,out_vendor_csv)

   For a call originating from the provided Client ID, on a
   wholesale or retail quality, going to dialled_no, the function
   removes the Vendors ( from the vendor_csv list ) which do not
   pass the desired_margin condition, and sets th out_vendor_csv
   variable to the list of Vendor that meet the margin condition,
   in descending order of their margin ( from most profitable
   Vendor to least profitable Vendor that still meets the margin
   condition )

   The client_id pseudo-var will hold the client_id originating
   this call

   The is_wholesale pseudo-var will contain either a 1 or a 0,
   depending on whether the call is wholesale or retail ( see
   client ratesheet provisioning ).

   The vendors_csv pseudo-var contains a list of Vendors that need
   to be filtered based on the desired margin ( keep just those
   that match your desired percentage margin for this call )

   The dialled_no pseudo-var contains the DNIS - the dialled
   number for the current call. It needs to be in E164 format,
   without the leading +

   The desired_margin pseudo-var contains the minimum Integer
   margin that the script writer wants to achieve, based on the
   Client sell and Vendor buy prices. The formula used is :
   vendor_margin=(client_price - results[i])*100/client_price) .
   If the vendor_margin is higher than the desired_margin, then
   the Vendor is ok to use. The desired margin can be positive (
   call will be profitable ) or negative ( the call will cause a
   loss ).

   The out_vendors_csv pseudo-var is an output parameter, and the
   pvar will get populated with the CSV list of Vendors that meet
   the desired margin condition

   Possible parameter types
     * ALL Parameters - String/Integer or pseudo-variables

   This function can be used from any route.

   Example 1.12. cost_based_ordering usage
...
# If we get a call from testClient on it's wholesale quality,
# going to number 40720018124, and we have to pick from the list
# of vendors 'testVendor,testVendor2' based on a a profit margin
# of 0 ( we do not want to lose money on this call ),
# then $avp(out_vendor_csv) will have the vendors that we need
# to use based on the above call characteristics, and the desired margin
# The order in $avp(carrierlist) does not matter, the vendors will be
# ordered from most profitable to least profitable
$avp(client_id)="testClient";
$avp(is_ws)=1;
$avp(carrierlist)="testVendor,testVendor2";
$avp(dnis)="40720018124";
$avp(profit_margin)=0;

if (cost_based_ordering("$avp(client_id)","$avp(is_ws)","$avp(carrierlis
t)","$avp(dnis)","$avp(profit_margin)","$avp(out_vendor_result)")) {
        xlog("XXX - Out of the $avp(carrierlist) carriers, we should onl
y use $avp(out_vendor_result) , in the provided order\n");

...

1.5. Exported MI Functions

1.5.1.  rc_addVendor

   Adds a new Vendor, without assigning any ratesheet to it.

   Name: rc_addVendor

   Parameters :
     * vendorName - name of the Vendor to be added

   MI FIFO Command Format:
## Add a new Vendor
# opensips-cli -x mi rc_addVendor myNewVendor

1.5.2.  rc_deleteVendor

   Removes a vendor from memory, along with the ratesheet asigned
   with it ( if any )

   Name: rc_deleteVendor

   Parameters :
     * vendorName - name of the Vendor to be deleted

   MI FIFO Command Format:
## Delete a Vendor
# opensipss-cli -x mi rc_deleteVendor myNewVendor

1.5.3.  rc_reloadVendorRate

   Reloads the provided ratesheet and assigns it to the Vendor

   Name: rc_reloadVendorRate

   Parameters :
     * vendorName - name of the Vendor
     * ratesheet_id - ID of the ratesheet to be reloaded and
       assigned

   MI FIFO Command Format:
## Reloads a Vendor Ratesheet
# opensips-cli -x mi rc_reloadVendorRate myVendor 3

1.5.4.  rc_deleteVendorRate

   Deletes the assigned ratesheet from the Vendor

   Name: rc_deleteVendorRate

   Parameters :
     * vendorName - name of the Vendor

   MI FIFO Command Format:
## Reloads a Vendor Ratesheet
# opensips-cli -x mi rc_deleteVendorRate myVendor

1.5.5.  rc_getVendorPrice

   Fetches all the ratesheet information ( destination name,
   price, minimum, increment ) for the provided Vendor and dialled
   number

   Name: rc_getVendorPrice

   Parameters :
     * vendorName - name of the Vendor
     * dialledNumber - number to match in the above Vendor's
       ratesheet

   MI FIFO Command Format:
## Query for the price of myVendor for the 4072731825 number
#/usr/local/bin/opensips-cli -x mi rc_getVendorPrice myVendor 4072731825
{
    "prefix": "40727",
    "destination": "ROMANIA MOBILE VODAFONE",
    "price": 0.05,
    "minimum": 1,
    "increment": 1,
    "currency": "USD"
}

1.5.6.  rc_addClient

   Adds a new Client, without assigning any ratesheet to it.

   Name: rc_addClient

   Parameters :
     * clientName - name of the Client to be added

   MI FIFO Command Format:
## Add a new Client
# opensips-cli -x mi fifo rc_addClient myNewClient

1.5.7.  rc_deleteClient

   Removes a Client from memory, along with the ratesheet asigned
   with it ( if any )

   Name: rc_deleteClient

   Parameters :
     * clientName - name of the Client to be deleted

   MI FIFO Command Format:
## Delete a Client
# opensips-cli -x mi rc_deleteClient myClient

1.5.8.  rc_reloadClientRate

   Reloads the provided ratesheet and assigns it to the Client

   Name: rc_reloadClientRate

   Parameters :
     * clientName - name of the Cient
     * isWholesale - is the ratesheet assigned on the wholesale or
       retail quality
     * ratesheet_id - ID of the ratesheet to be reloaded and
       assigned

   MI FIFO Command Format:
## Reloads the Client's wholesale Ratesheet, assigning it rate id 3
# opensips-cli -x mi rc_reloadClientRate myClient 1 3

1.5.9.  rc_deleteClientRate

   Deletes the assigned ratesheet from the Client

   Name: rc_deleteClientRate

   Parameters :
     * ClientName - name of the Client
     * isWholesale - delete the wholesale or retail ratesheet

   MI FIFO Command Format:
## Reloads a Vendor Ratesheet
# opensips-cli -x mi rc_deleteVendorRate myVendor

1.5.10.  rc_getClientPrice

   Fetches all the ratesheet information ( destination name,
   price, minimum, increment ) for the provided Client, on the
   specified quality ( wholesale vs retail ) and dialled number

   Name: rc_getClientPrice

   Parameters :
     * ClientName - name of the Client
     * isWholesale - wholesale = 1, retail = 0
     * dialledNumber - number to match in the above Client's
       ratesheet

   MI FIFO Command Format:
## Query for the price of myClient, on the retail quality, for the 40727
31825 number
#/usr/local/bin/opensips-cli -x mi rc_getClientPrice myClient 0 40727318
25
{
    "prefix": "40727",
    "destination": "ROMANIA MOBILE VODAFONE",
    "price": 0.03,
    "minimum": 1,
    "increment": 1,
    "currency": "USD"
}


Chapter 2. Contributors

2.1. By Commit Statistics

   Table 2.1. Top contributors by DevScore^(1), authored
   commits^(2) and lines added/removed^(3)
                   Name               DevScore Commits Lines ++ Lines --
   1. Vlad Paiu (@vladpaiu)              30       3      3167      1
   2. Maksym Sobolyev (@sobomax)         5        3       18       19
   3. Callum                             4        2       3        3
   4. Razvan Crainea (@razvancrainea)    3        1       6        4
   5. Artiom Druz                        2        1       1        0

   (1) DevScore = author_commits + author_lines_added /
   (project_lines_added / project_commits) + author_lines_deleted
   / (project_lines_deleted / project_commits)

   (2) including any documentation-related commits, excluding
   merge commits. Regarding imported patches/code, we do our best
   to count the work on behalf of the proper owner, as per the
   "fix_authors" and "mod_renames" arrays in
   opensips/doc/build-contrib.sh. If you identify any
   patches/commits which do not get properly attributed to you,
   please submit a pull request which extends "fix_authors" and/or
   "mod_renames".

   (3) ignoring whitespace edits, renamed files and auto-generated
   files

2.2. By Commit Activity

   Table 2.2. Most recently active contributors^(1) to this module
                   Name                 Commit Activity
   1. Maksym Sobolyev (@sobomax)      Jan 2021 - Feb 2023
   2. Callum                          Nov 2022 - Nov 2022
   3. Artiom Druz                     Jul 2021 - Jul 2021
   4. Vlad Paiu (@vladpaiu)           Mar 2020 - Jul 2020
   5. Razvan Crainea (@razvancrainea) Jul 2020 - Jul 2020

   (1) including any documentation-related commits, excluding
   merge commits

Chapter 3. Documentation

3.1. Contributors

   Last edited by: Callum, Vlad Paiu (@vladpaiu).
