To configure the RebateManagerRebates module, so that you can create new rebate agreementsRebate Agreements, take the following steps:
- Make sure you have the following prerequisites ready:
- Customer master
- Product master
- Datamart
- Create a Rebate calculation logic.
- Create a Rebate Condition Type.
- Create a Rebate Agreement.
- Create Rebate Records.
- Create a workflow for rebate and payout approval.
- Create an allocation calculation logic for allocating data to a datamartDatamart.
Rebate Calculation Logic
Rebate calculation logic is used to calculate:
...
Element Name | Calculation Context | Groovy | Note |
---|
ProductGroup |
| api.productGroupEntry() | The conditions are typically negotiated for a group of products. |
CustomerGroup |
| api.customerGroupEntry() | The conditions are typically negotiated for a group of customers. |
RebateDiscount |
| api.userEntry("RebateDiscount") / 100.0
| The negotiated condition – in this case the discount in percentage. |
AbortOnSyntaxCheck |
| if (api.isSyntaxCheck()) api.abortCalculation() |
|
Today |
| return api.targetDate() | This is to be able to simulate different "today" |
StartDate |
| return (api.currentItem()?.startDate) ? api.parseDate("yyyy-MM-dd",api.currentItem().startDate) : new Date() |
|
EndDate |
| return (api.currentItem()?.endDate) ? api.parseDate("yyyy-MM-dd",api.currentItem().endDate) : new Date() |
|
EndDateOrToday |
| return (api.getElement("Today") < api.getElement("EndDate")) ? api.getElement("Today") : api.getElement("EndDate") |
|
ActualSales |
| def dmCtx = api.getDatamartContext()
def salesDM = dmCtx.getDatamart("Transactions")
def datamartQuery = dmCtx.newQuery(salesDM,true)
datamartQuery.select("SUM(Invoice_Price)", "IP")
datamartQuery.where(
Filter.greaterOrEqual("Invoice_Date",api.getElement("StartDate")),
Filter.lessOrEqual("Invoice_Date",api.getElement("EndDateOrToday"))
)
datamartQuery.where(api.getElement("CustomerGroup"))
datamartQuery.where(api.getElement("ProductGroup"))
def result = dmCtx.executeQuery(datamartQuery)
return (result?.getData()?.getValue(0,0)?:0.0)
| How much money were actually spent in the time frame. The number comes from Datamart for the specified period. |
Rebate |
| def sales = api.getElement("ActualSales")
def rebatePct = api.getElement("RebateDiscount")
return (sales != null && rebatePct != null) ? (sales * rebatePct) : null
| SimpleRebate calculation – we will pay back the customer the negotiated percentage of the spendings on the given group of products. |
ForecastSales |
| def sales = api.getElement("ActualSales")
if (sales<=0) sales=0
if (sales > 0) {
def from = api.getElement("StartDate")
def to = api.getElement("EndDate")
def today = api.targetDate()
if (today > to ) return sales
else if (today < from) return 0.0
else {
int totalDays = to - from + 1
def daysofTransactions = today - from + 1
def perDaySales = sales / daysofTransactions
//api.trace("validity", from as String, to as String)
//api.trace("totalDays", totalDays)
//api.trace("daysofTransactions",daysofTransactions)
return perDaySales * totalDays
}
}
|
|
ForecastRebate |
| def sales = api.getElement("ForecastSales")
def rebatePct = api.getElement("Rebate")
return (sales != null && rebatePct != null) ? (sales * rebatePct) : null
|
|
RebateRecordCreate | Agreement | rebateRecords.add()
/*
rebateRecords.add([
"attribute1":api.getElement("Rebate"),
"attribute2":api.getElement("TotalSales"),
"attribute3":api.getElement("RebateDiscount")
])
*/
| Every agreement line will generate one Rebate Record (i.e., there will be only one payout at the end of the year). |
RRInput | RebateRecord | api.userEntry("RRInput") | This is an example of how to make an input specific for the Rebate Record. |
CalculationBase | RebateRecord | calculationBase.clear()
calculationBase.include(api.getElement("CustomerGroup"))
calculationBase.include(api.getElement("ProductGroup"))
calculationBase.include( new TimePeriod(api.getElement("StartDate"), api.getElement("EndDateOrToday"), TimeUnit.DAY) )
calculationBase.setDateFieldName("InvoiceDate")
| Calculation base specifies a filter which finds the sales transactions related to this Rebate Record. |
...
Condition Type
You need to create a new Rebate Condition Type:
Label | Pricing Logic | Waterfall Element |
---|
Rebate Bonus | <your Rebate Calculation Logic> | This OOTB column is here only in case you would like to use it. Here you can store the name of the waterfall element which is influenced by this Rebate. |
Now you can create a new Rebate Agreement and add a new line using the new Rebate Condition Type. See Add/Edit Rebate Agreements How to Create a Rebate Agreement for details.
Rebate Records
Rebate Records are calculations of how much rebate will be paid out to customer, rebate estimations, etc. One Rebate Record represents one payout.
...
For more information, see Rebate Records.
Rebate Record Calculation Results Mapping to the Attributes
After you calculate the RR and Save save it, the Calculation Result can be mapped to the Attributes of the Rebate Record.
...
The mapping rules are the same as for Price Record, i.e., when the name of the Element of the Rebate Type Logic is the same as the name of the attribute column (or the RR), the system will copy the element result value into the attribute.
If you want to allocate the rebate money (paid to the customer) back to the sales transactions you need to create:
Table of Content Zone |
---|
|
Type | Element Name | Expression |
---|
Formula | StartDate | DateUserEntry("StartDate") | Formula | EndDate | DateUserEntry("EndDate") | Groovy | EmitRebateRecords | if(api.isSyntaxCheck())return
def startDate = api.getElement("StartDate")
def endDate = api.getElement("EndDate")
if(startDate == null || endDate == null){
def cal = api.datamartCalendar()
def year = cal.getTimePeriod(cal.getYear(api.targetDate()))
startDate = year.getStartDate()
endDate = year.getEndDate()
}
def filter = Filter.and(
Filter.greaterOrEqual("startDate", startDate),
Filter.lessOrEqual("endDate",endDate)
)
def dateFieldName = "Invoice_Date"
def sortRRByField = "startDate"
api.emitRebateRecords(dateFieldName, sortRRByField, filter)
|
PriceAnalyzer Type | Element Name | Display Mode | Groups | Expression | Description |
---|
Formula | InvoicePrice | Never | Row | UserEntry("InvoicePrice") | Invoice price of the transaction (to which we allocate the rebate). | Formula | PreviousRebate | Never | Row | UserEntry("PrevRebate") | Actual Rebate value on the transaction (to which we allocate the rebate). | Formula | Rebate | Everywhere | Row | PreviousRebate + (InvoicePrice * CurrentItem("attribute1") / CurrentItem("attribute3")) | The result Rebate value, which should be on the Transaction after adding the Rebate from the Rebate Record. The CurrentItem() returns the Rebate Record being allocated. We take only proportional part of the Rebate. attribute1 is the Rebate value of the Rebate Record to be allocated. attribute3 is the Total Sales (i.e. summary of Invoice Prices of all the transactions which were used to calculate the Rebate). |
Create a new Calculation Data Load: - Formula – Your new allocation PA Analytics logic.
- Feeder – Your new Feeder logic.
- Input Start Date – Typically set to the beginning of the year, where you want to allocate.
- Input End Date – Typically set to the end of the year, where you want to allocate.
- Formula Input (Source Field Mapping)
- InvoicePrice – Transaction column "Invoice Price".
- PreviousRebate – Transaction column "Rebate".
- Formula Outputs (Target Fields)
- Rebate – The output mapping is done in the way that the element name must equal the column name (of the transaction).
Before you run the allocation data load, you need to have some Rebate Records for that period, otherwise not much happens. |
...