Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

To configure the Rebates module, so that you can create new Rebate Agreements, take the following steps:

  1. Make sure you have the following prerequisites ready:

    • Customer master

    • Product master

    • Datamart

  2. Create a Rebate calculation logic.

  3. Create a Condition Type.

  4. Create a Rebate Agreement.

  5. Create Rebate Records.

  6. Create a workflow for rebate and payout approval.

  7. Create an allocation calculation logic for allocating data to a Datamart.

Rebate Calculation Logic

Rebate calculation logic is used to calculate:

  • Rebate Agreement Line

  • Rebate Agreement Line (Read-only) – for approved Agreements

  • Rebate Record

Because the logic is almost the same for all of these objects, you define only one logic, and if an element is specific only to some of these objects, you set the "Group" of the element.

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.

AbortOnInputGeneration


if (api.isInputGenerationExecution()) api.abortCalculation()

isInputGenerationExecution is supported from version 10.0, in older versions use isSyntaxCheck.

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 Condition Type:

Label

Pricing Logic

Waterfall Element

Rebate Bonus

<your Rebate Calculation Logic>

Use this out-of-the-box column only if needed. You can store here the name of the waterfall element which is influenced by this Rebate.

Rebate Agreement

Now you can create a new Rebate Agreement and add a new line using the new Condition Type. See How to Create a Rebate Agreement for details.

...

Rebate Records are calculations of how much rebate will be paid out to customer, rebate estimations, etc. One Rebate Record represents one payout.

Rebate Records are:

  • Calculated after the agreement validity period to find out how much rebate will be paid.

  • Submitted for approval before the money is actually paid out to the customer.

  • Sent to SAP to process the payment.

The record has over /wiki/spaces/KB/pages/99570047 that can be used.

...

If you want to allocate the rebate money (paid to the customer) back to the sales transactions you need to create:

Table of Contents

...

minLevel2
maxLevel2

...

outlinefalse
stylenone
typelist
printabletrue

Feeder Logic (in Price Setting)

Type

Element Name

Expression

Formula

StartDate

DateUserEntry("StartDate")

Formula

EndDate

DateUserEntry("EndDate")

Groovy

EmitRebateRecords

if(api.isInputGenerationExecution())return //isInputGenerationExecution is supported from version 10.0, in older versions use isSyntaxCheck.

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)

Allocation Logic (in Analytics > Data Manager)

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.

  • 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).

Data Load

Create a new Calculation Data Load:

  • Formula – Your new allocation 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 a 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.