...
Navigate to Rebates Condition Types
Add new Condition Type "Bonus On Sales"
Figure 2. Creation of new Condition Type (without logic)
set the Name to "BonusOnSales"
set the Label to "Bonus On Sales"
...
In Pricefx Studio, create new logic of type Pricing logic with Formula nature “Rebate (rebateAgreement)”
Name it “BonusOnSales”
Set Validity reasonably in the past (to be able to test for past dates) – e.g. 2000-01-01
Read inputs ProductGroup, CustomerGroup and Rebate% from the user. Create elements:
CustomerGroup
Code Block return api.customerGroupEntry()
During InputGeneration it builds the input field. During regular execution it returns the value selected by user, but encapsulated in an object of CustomerGroup type, which is later expected in where clause of query to Datamart. If the value was entered on the Header level, it will be inherited in this field, and the user can override the selection.
ProductGroup
Code Block return api.productGroupEntry()
During InputGeneration it builds the input field. During regular execution it returns the value selected by user, but encapsulated in an object of ProductGroup type, which is later expected in where clause of query to Datamart.
RebatePct
Code Block final String INPUT_REBATE_PCT = "RebatePct" if (api.isInputGenerationExecution()) { api.userEntry(INPUT_REBATE_PCT) api.getParameter(INPUT_REBATE_PCT) .setConfigParameter("formatType", "PERCENT") .setRequired(true) .setLabel("Rebate %") } else { return input[INPUT_REBATE_PCT] }
AbortOnSyntaxCheck
Code Block if (api.isInputGenerationExecution()) { api.abortCalculation() }
set the Display Mode of those elements to "Never"
do not set any Calculation Context of those elements
Setup calculation of the Sales Forecast:
As we are negotiating the agreement in the middle of the year in which the agreement is valid, make the linear forecast (for the full validity period) based on the sales which the customer group has made from the startDate until today – i.e. based on the Actual Sales_
“Past” Transactions - before the Agreement
Transactions which falls into the range of the Agreement
Transactions, which we have in the system (because we’re testing “in the past”), but we cannot consider them for calculations, because under normal conditions, they would NOT be in the system yet.
remember, you normally do NOT have in the Datamart any transactions after Today! The only reason, why we have them is, that we’re testing on the historical dataset and we’re pretending that Today is in the past
Prepare the date ranges - To calculate the ActualSales, we need to make a query to Datamart, and for that we need to know the date range
Today
Code Block return api.targetDate()
StartDate
Code Block def startDateAsString = api.currentItem()?.startDate if (startDateAsString) { return api.parseDate("yyyy-MM-dd", startDateAsString) } else { return out.Today /* fallback */ }
EndDate
Code Block def endDateAsString = api.currentItem()?.endDate if (endDateAsString) { return api.parseDate("yyyy-MM-dd", endDateAsString) } else { return out.Today /* fallback */ }
EndDateOrToday
Code Block return out.Today < out.EndDate ? out.Today : out.EndDate
with exception of element "Today", set Display Mode of those elements to Never
do not set any Calculation Context of those elements
Calculate the Actual Sales – create element “ActualSales”:
Example 1. Code of Element "ActualSales"
Code Block def dmCtx = api.getDatamartContext() def dmTable = dmCtx.getDatamart("Transaction") def query = dmCtx.newQuery(dmTable, true) .select("SUM(InvoicePrice)", "TotalRevenue") .where(out.CustomerGroup) .where(out.ProductGroup) .where( Filter.greaterOrEqual("InvoiceDate", out.StartDate), Filter.lessOrEqual("InvoiceDate", out.EndDateOrToday) ) def result = dmCtx.executeQuery(query) return (result?.getData()?.getValue(0, 0) ?: 0.0)
Ensure the result will be visible for the user.
do not set any Calculation Context of this element
format the result money with € currency
Calculate the Sales Forecast, based on the knowledge of the Actual Sales.
Example 2. Code of Element "ForecastSales"
Code Block if (out.Today > out.EndDate) { return out.ActualSales } if (out.Today < out.StartDate) { return null } Integer daysOfLineValidity = out.EndDate - out.StartDate + 1 Integer daysOfTransactions = out.Today - out.StartDate + 1 BigDecimal actualSalesPerDay = out.ActualSales / daysOfTransactions return actualSalesPerDay * daysOfLineValidity
Ensure the result will be visible for the user.
do not set any Calculation Context of this element
format the result money with € currency
Calculate the Rebate Forecast - create element “ForecastRebate”. Ensure the result will be visible.
Rebate Forecast is how much money we are forecasting to give to the customer, based on the sales forecast and the negotiated rebate percentage.
Example 3. Code of Element "ForecastRebate"
Code Block if (out.ForecastSales != null && out.RebatePct != null) { return out.ForecastSales * out.RebatePct }
Ensure the result will be visible for the user.
do not set any Calculation Context of this element
format the result money with € currency
Test the Logic:
Set all the Parameters
Context must be set to Condition Type, as we’re testing the logic of line item (and line item is of certain Condition Type)
For inspiration of date parameter values, use the Test Case written at the beginning of this Lab.
Remember to click Generate Parameter so that the logic generates the other parameters.
Note: you can ignore the Target Date parameter, it will be replaced by value of Calculation Date anyway
for Customer(s), click on the magnifying glass icon, and setup the filter
for Product(s), click on the magnifying glass icon, and setup the filetr ProductGroup = Beef
and then Test the logic and verify you get correct results from Datamart.
Do test for different combinations of
Start and End dates
Product and Customer Groups
to get numbers for verification/comparison of DM queries results returned by your logic, the easiest and quick way to get summaries of Datamart, use the PriceAnalyzer → Data Analyzer → Data Table and simulate the required calculation there as well.
Deploy the verified logic to the partition.
...
Navigate to RebateManager Condition Types
Add new Condition Type “Bonus On Sales”, set the Pricing Logic to your new logic BonusOnSales
Figure 3. Condition Type, selection of Pricing Logic, which will calculate it
Hint: if you cannot see the newly deployed logic, reload the browser
...
Verify the new Condition type by making a new Rebate Agreement
Create new Rebate Agreement
Navigate to RebateManager Rebate Agreements
Use button New Rebate Agreement
Setup Header Info: Start Date, End Date, Payout Date, Calculation Date and Customer Group according the Test Case.
Figure 4. Screenshot of Rebate Agreement → Header detail screen, with header inputs set
Add new Line Item
Navigate to “Items” section/tab
Select your new Condition Type - either click on the "down" arrow in the input "Browse Items" or click on the "+ Add Items" button next to it
Figure 5. Screenshot of Rebate Agreement → Items screen, adding new line
Select the Bonus On Sales Condition Type
Result: The system will add the line item and immediately calculate it, so you will likely see some exclamation marks, because you haven’t had chance to fill in the inputs.
Figure 6. Screenshot of Rebate Agreement → Items screen, new line added
Setup the inputs for the Line Item
Review the Customer Group inherited from the header
Select the Product Group, and Rebate % according the Test Case and recalculate
Result: there should be no errors, and the required results should be correctly calculated
Figure 7. Screenshot of Rebate Agreement → Items screen, inputs set and recalculated
Save the Rebate Agreement