...
Prepare the new Rebate Logic:
In Studio, make a copy of the BonusOnSales logic
edit the file logic.json of this new logic and change of this copy to "BonusOnSalesWithPayoutRecords". This action should not only change the name of logic inside of the Json file, but also the name of the folder with logic.
Deploy the logic to your partition
prepare a new Rebate Type to use this logic:
In Pricefx UI, navigate to Rebates Condition Types
create a new Condition Type "BonusOnSalesWithPayoutRecords" which uses as Pricing Logic the new logic BonusOnSalesWithPayoutRecords
...
In Studio, open your logic BonusOnSalesWithPayoutRecords
Add the code, which queries Actual Sales per Customer
Add a new Element "ActualSalesPerCustomer" right before the element "ActualSales". The code will be:
Code Block def dmCtx = api.getDatamartContext() def dmTable = dmCtx.getDatamart("Transaction") def query = dmCtx.newQuery(dmTable, true) .select("CustomerId", "CustomerId") .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?.data?.collectEntries { row -> [(row.CustomerId): row.TotalRevenue] }
use Roll Up / Group Bygroup Actual Sales by CustomerIdcreate a Map with data: CustomerId → ActualSales
This Element ActualSalesPerCustomer will be used in all contexts, so either keep Calculation Contexts Agreement, Agreement ReadOnly and RebateRecord all blanks or all crossed
to avoid querying the data 2x for the same reason, modify the code of existing element ActualSales, so that it only summarizes the data found in element ActualSalesPerCustomer. So the code of ActualSales element will be:
Code Block return (out.ActualSalesByCustomer as Map)?.values()?.sum()
Add the code, which generates the Payout Records:
Add new Element "CreatePayoutRecords" to the end of the logic, with code:
Code Block if (out.RebatePct == null) return def actualSales = out.ActualSalesByCustomer as Map def customerIds = actualSales.keySet() def rebateRecord = api.currentItem() payoutRecords.bulkLoadMode() customerIds.each { customerId -> def rebateValue = (actualSales[customerId] ?: 0.0) * out.RebatePct def payoutRecord = [ startDate : rebateRecord.startDate, endDate : rebateRecord.endDate, payoutDate: rebateRecord.payoutDate, attribute1: customerId, attribute2: rebateValue, attribute3: "EUR", attribute4: out.RebatePct, ] payoutRecords.add( "Payout", "${rebateRecord.uniqueName}-${customerId}" as String, payoutRecord ) } payoutRecords.flush()
start the Bulk Mode, which helps with speed when generating many thousands of PayoutRecords. If you generate lower amounts, you might not use it and simply commenting out this line should keep the functionality.create the new Payout Record. If the record already existed, it will be updated.use flush() to ensure, that your new records are fully stored in tables. This is a must have for bulk-mode, but not needed for non-bulk mode. Since it’s ok to use it also in non-bulk mode, you can simply use it all the times, once you’re done with generation of the Payout Records.
This Element "CreatePayoutRecords" is used ONLY when recalculating Rebate Records, so ensure, that only the Calculation Context "RebateRecord" is crossed
Test the Logic in Studio
in Studio you must test, if your logic is executed without failure, but you cannot test the "writing" of the data to the tables - the writing operation works only in non-testing execution.
setup the input parameters
Context - ensure to select REBATERECORD
RebateRecordName - type a name of existing Rebate Record - e.g. the one you created for testing purposes at the beginning.
startDate, endDate - choose a timeframe, where you know you have data in your Datamart. You can use the same you used while creating the Agreement.
calculation Date - will be used as Target Date. In the code, the Target Date is used to find the period of time for which we search the data.
targetDate - not used, the value does not matter, because it will be overriden by calculationDate
as Studio has the possibility to save the parameters, we strongly encourage you to use it, so that you will not loose the values, when you close the Logic or Studio. In the screenshot you can notice the Load Preset Test RR.
Verify, if the logic passed ok, and the values of the ActualSalesByCustomer, if you got realistis numbers.
you can also add
api.trace()
to element CreatePayoutRecords to visualize, if the PayoutRecords are asked to be created.Remember, they will not be physically created in the Test mode.
Test the logic in Pricefx UI
You will test it on the Rebate Record detail page. So navigate to RebateManager Rebates Rebate Records
click on your Rebate Record’s ID (it’s a link), to open its detail page
click on Calculate to recalculate the Rebate Record - since the same logic also creates the Payout Records, they will be created
you do not need to Save the calculated result to "save" the Payout Records. They’re created already during the execution of the Logic.
Please note, that the Save cause Calculation and only then saves. So if the users would use manually this detail page for recalculations, they must be trained to properly understand, how buttons Calculate and Save work.
Remember, that the Rebate Records are typically calculated by the Rebate Calculation job, where the logic executes ones (and stores the Payout Records to database and prepares the values for Rebate Record), and then the Rebate Record values are persisted too.
review the PayoutRecords list - navigate to RebateManager Rebates Payout Records and review the data in the columns
verify, that you have more customers and they have different rebates. Of course, this depends on the data set, date-ranges, etc., so validate it with respect to your dataset.
...
Rename and Customize columns of the Payout Records
in Pricefx UI, navigate to RebateManager Rebates Payout Records
for columns attribute1..4 use Rename and Customize columns to set up properties of the columns
AttributeNameLabelTypeFormat Type
attribute1
CustomerId
Customer Id
String
-
attribute2
ActualRebate
Actual Rebate
Real
Money
attribute3
Currency
Currency
String
-
attribute4
RebatePct
Rebate %
Real
Percent
fetch definition into project
in Studio, fetch the object Payout record attr (PYR), PayoutRecordAttribute to your project
...