Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: PFUN-16763

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

...

Element NameCalculation ContextGroovyNote
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.
AbortOnSyntaxCheckAbortOnInputGeneration
if (api.isSyntaxCheckisInputGenerationExecution()) 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


RebateRecordCreateAgreement

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).
RRInputRebateRecordapi.userEntry("RRInput")This is an example of how to make an input specific for the Rebate Record.
CalculationBaseRebateRecord

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.

...

Table of Content Zone
maxLevel2
locationtop

Feeder Logic (in Price Setting)

TypeElement NameExpression
FormulaStartDateDateUserEntry("StartDate")
FormulaEndDateDateUserEntry("EndDate")
GroovyEmitRebateRecords

if(api.isSyntaxCheckisInputGenerationExecution())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)

Allocation Logic (in Analytics > Data Manager)

TypeElement NameDisplay ModeGroupsExpressionDescription
FormulaInvoicePriceNeverRowUserEntry("InvoicePrice")Invoice price of the transaction (to which we allocate the rebate).
FormulaPreviousRebateNeverRowUserEntry("PrevRebate")Actual Rebate value on the transaction (to which we allocate the rebate).
FormulaRebateEverywhereRowPreviousRebate + (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.

...