Versions Compared

Key

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

...

  1. Prepare the new Rebate Logic:

    1. In Studio, make a copy of the BonusOnSales logic

    2. 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.

      logic name changeImage Modified
    3. Deploy the logic to your partition

  2. prepare a new Rebate Type to use this logic:

    1. In Pricefx UI, navigate to Rebates  Condition Types

    2. create a new Condition Type "BonusOnSalesWithPayoutRecords" which uses as Pricing Logic the new logic BonusOnSalesWithPayoutRecords

...

  1. In Studio, open your logic BonusOnSalesWithPayoutRecords

  2. Add the code, which queries Actual Sales per Customer

    1. 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

    2. This Element ActualSalesPerCustomer will be used in all contexts, so either keep Calculation Contexts Agreement, Agreement ReadOnly and RebateRecord all blanks or all crossed

    3. 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()
  3. Add the code, which generates the Payout Records:

    1. 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.

    2. This Element "CreatePayoutRecords" is used ONLY when recalculating Rebate Records, so ensure, that only the Calculation Context "RebateRecord" is crossed

  4. Test the Logic in Studio

    1. 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.

    2. setup the input parameters

      test logic 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

    3. 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.

    4. Verify, if the logic passed ok, and the values of the ActualSalesByCustomer, if you got realistis numbers.

      test logic resultsImage Modified
    5. you can also add api.trace() to element CreatePayoutRecords to visualize, if the PayoutRecords are asked to be created.

      1. Remember, they will not be physically created in the Test mode.

  5. Test the logic in Pricefx UI

    1. You will test it on the Rebate Record detail page. So navigate to RebateManager Rebates  Rebate Records

    2. click on your Rebate Record’s ID (it’s a link), to open its detail page

    3. 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.

    4. review the PayoutRecords list - navigate to RebateManager Rebates  Payout Records and review the data in the columns

      payout recordsImage Modified
      1. 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.

...

  1. Rename and Customize columns of the Payout Records

    1. in Pricefx UI, navigate to RebateManager Rebates  Payout Records

    2. 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

  2. fetch definition into project

    1. in Studio, fetch the object Payout record attr (PYR), PayoutRecordAttribute to your project

...