Dayalan Punniyamoorthy Blog

Monday, May 6, 2024

Multiple Rules of Enterprise Profitability and Cost Management (EPCM) using Groovy in Sequential Manner!

In this blog we will see how to run multiple Rules of Enterprise Profitability and Cost Management (EPCM) using Groovy in Sequential and proceed with the next rule only after completion the previous rule.











 

/**************************************************************************************/

/*                  Run IC Calcs All Region                                                                     */

/*                  Creation Date       : 10th Apr 2024                                                  */

/*                  Version                   : 1.0                                                                    */

/*                  Modifications         :                                                                        */

/*       The Rule uses the Sub Var &CurMth, &CurYr.                                          */

/*  The Rule will be executing the following,                                                     */

/*       1. Clear for EMEA                                                                                          */

/*        2. Clear for APAC                                                                                         */

/*        3. Clear for Americas                                                                                   */

/*       4. Merge Slices                                                                                         */

/*       5. Run Ruleset Ranges:                                                                            */

/*                  Start   End                                                                                      */

/*                  1            999                                                                                   */

/**************************************************************************************/

connectionName is a variable that stores the name of the connection to the server. In this case, it's set to 'Localhost'. This variable is later used to specify which server to connect to when making HTTP requests. 

def connectionName = 'Localhost'

Closure subVarValue = { String subVar -> operation.application.getSubstitutionVariable(subVar).value }

String CurYr = subVarValue('CurYr')

String CurMth = subVarValue('CurMth')

println "The Rule is using the Sub Var Current Year : " +CurYr +" " + "Current Month : " +CurMth

 Here, a closure named subVarValue is defined. A closure is essentially a block of code that can be assigned to a variable and executed later.

This closure takes a single parameter subVar, which is a string representing a substitution variable.

Within the closure, it retrieves the value of the substitution variable specified by subVar using operation.application.getSubstitutionVariable(subVar).

Finally, it returns the value of the substitution variable using .value.

This invokes the closure subVarValue with the argument 'CurYr'. & CurMth. This means it fetches the value of the substitution variable named 'CurYr' & ‘CurMth’.The result is assigned to the variables.


/* Wait for the Rules to complete */

boolean WaitforCompletion

HttpResponse<String> jsonResponse

def payload

def awaitCompletion(HttpResponse<String> jsonResponse, String connectionName, String operation) {

    final int IN_PROGRESS = -1

    if (!(200..299).contains(jsonResponse.status)) {

        throwVetoException("Error occured: $jsonResponse.statusText")

    }

    // Parse the JSON response to get the status of the operation. Keep polling the DM server until the operation completes.

    ReadContext ctx = JsonPath.parse(jsonResponse.body)

    int status = ctx.read('$.status')

    for(long delay = 50; status == IN_PROGRESS; delay = Math.min(1000, delay * 2)) {

        sleep(delay)

        status = getJobStatus(connectionName, (String)ctx.read('$.jobId'))

    }

 

    println("$operation ${status == 0 || status == -1 ? "successful" : "failed"}.\n")

    return status == 0

}

This code defines a function awaitCompletion that waits for a job to complete by polling the server until the operation finishes. It checks the status of the job in the JSON response and sleeps for increasing intervals until the job status changes from in-progress to completion or failure. If the HTTP response status indicates an error, it throws an exception.

 

int getJobStatus(String connectionName, String jobId) {

    HttpResponse<String> pingResponse = operation.application.getConnection(connectionName).get("/rest/v3/applications/ICPCM/jobs/" + jobId).asString()

    return JsonPath.parse(pingResponse.body).read('$.status')  

}

This function, getJobStatus, retrieves the status of a job by sending a GET request to the server's API endpoint for fetching job status. It utilizes the provided connectionName to determine which server to connect to. The response is then parsed using JsonPath to extract the job status, which is returned as an integer value representing the job's current status code.

     /**********************************************************************************************/

    /*      1. Clear for EMEA                                                                                                       */

    /*      Rule Name:  Clear_for_EMEA_IC_Calcs                                                                  */

    /*********************************************************************************************/

    println "1.  Clear for EMEA"

 jsonResponse = operation.application.getConnection("Localhost").post('/rest/v3/applications/ICPCM/jobs')

    .header("Content-Type", "application/json")

    .body(json([

        "jobType" : "Clear Cube",

        "jobName" : "Clear_for_EMEA_Calcs"

        ])

    )

    .asString();

    println 'Response Received'

    println jsonResponse.body

 WaitforCompletion = awaitCompletion(jsonResponse, "Localhost", "Clear Cube")

This code segment initiates a "Clear for EMEA" operation by sending a POST request to the server's API endpoint for creating jobs. It specifies the job type as "Clear Cube" and provides a job name "Clear_for_EMEA_Calcs". The response received is printed to the console, and then the script waits for the completion of this operation by calling the awaitCompletion function with the appropriate parameters.

 

    /***********************************************************************************************/

/*      2. Clear for APAC                                                                                                    */

/*      Rule Name:  Clear_for_APAC_IC_Calcs                                                                */

/**********************************************************************************************/

    println "2.  Clear for APAC"

 jsonResponse = operation.application.getConnection("Localhost").post('/rest/v3/applications/ICPCM/jobs')

    .header("Content-Type", "application/json")

    .body(json([

        "jobType" : "Clear Cube",

        "jobName" : "Clear_for_APAC_IC_Calcs"

        ])

    )

    .asString();

    println 'Response Received'

    println jsonResponse.body

 WaitforCompletion = awaitCompletion(jsonResponse, "Localhost", "Clear Cube")

This code segment initiates a "Clear for APAC" operation by sending a POST request to the server's API endpoint for creating jobs. It specifies the job type as "Clear Cube" and provides a job name "Clear_for_APAC_Calcs". The response received is printed to the console, and then the script waits for the completion of this operation by calling the awaitCompletion function with the appropriate parameters.

     /************************************************************************************************/

    /*      3. Clear for Americas                                                                                                */

    /*      Rule Name:  Clear_for_Americas_IC_Calcs                                                           */

   /**********************************************************************************************/

    println "3.  Clear for Americas"

 jsonResponse = operation.application.getConnection("Localhost").post('/rest/v3/applications/ICPCM/jobs')

    .header("Content-Type", "application/json")

    .body(json([

        "jobType" : "Clear Cube",

        "jobName" : "Clear_for_Americas_IC_Calcs"

        ])

    )

    .asString();

    println 'Response Received'

    println jsonResponse.body

 WaitforCompletion = awaitCompletion(jsonResponse, "Localhost", "Clear Cube")

Similarly for running the code for Americas in this part of the code.   

    /************************************************************************************************/

    /*      4. Merge Data Slices                                                                                 */

    /*      Rule Name:  Merge Data Slices PCM.PCM_CLC                                                          */

    /************************************************************************************************/

    println "4.  Merge Data Slices"

           jsonResponse = operation.application.getConnection("Localhost").post('/rest/v3/applications/PCM/jobs')

    .header("Content-Type", "application/json")

    .body(json([

        "jobType" : "Merge Data Slices",

        "jobName" : "Merge Data Slices PCM.PCM_CLC",

        "parameters": [

        "cubeName": "PCM_CLC",

        "mergeSliceType": "allIncrementalSlicesInMain",

        "keepZeroCells": "false"

    ]

        ])

    )

    .asString();

    println 'Response Received'

    println jsonResponse.body

 WaitforCompletion = awaitCompletion(jsonResponse, "Localhost", "Merge Data Slices")

This code segment initiates a "Merge Data Slices" operation by sending a POST request to the server's API endpoint for creating jobs. It specifies the job type as "Merge Data Slices" and provides a job name "Merge Data Slices ICPCM.PCM_CLC". Additionally, it includes parameters such as the cube name ("PCM_CLC"), the merge slice type, and whether to keep zero cells. The response received is printed to the console, and then the script waits for the completion of this operation by calling the awaitCompletion function with the appropriate parameters.

    /************************************************************************************************/

/*      5. Run Calculation                                                                                                    */

/************************************************************************************************/

    println "5  Run Calculation for Range - 1 TO 999"

 jsonResponse = operation.application.getConnection("Localhost").post('/rest/v3/applications/ICPCM/jobs/')

    .header("Content-Type", "application/json")

    .body(json([

    "jobType":"Calculation",

    "jobName":"Run Calculation for Range - 1 TO 999",

    "parameters":[

        "povDelimiter":":",

        "povName":"$CurYr:$CurMth:Actual:Working",,

        "modelName":"2-IC Calcs",

        "executionType":"RULESET_SUBSET",

        "rulesetSeqNumStart":"1",

        "rulesetSeqNumEnd":"999",

        "clearCalculatedData":"true",

        "executeCalculations":"true",

        "optimizeForReporting":"true",

        "captureDebugScripts":"false"]

        ])

    )

    .asString();

          println 'Response Received'

          println jsonResponse.body

 WaitforCompletion = awaitCompletion(jsonResponse, "Localhost", "Run Calculation for Range - 1 TO 999")

This code segment initiates a "Run Calculation" operation for a specified range (1 to 999) by sending a POST request to the server's API endpoint for creating jobs. It specifies the job type as "Calculation" and provides a job name "Run Calculation for Range - 1 TO 999". Additionally, it includes parameters such as the point of view (pov) name, model name, execution type, ruleset sequence numbers, and other configuration options. The response received is printed to the console, and then the script waits for the completion of this operation by calling the awaitCompletion function with the appropriate parameters. 

 

// Print a message indicating the user who executed the rule

println("Rule was executed by $operation.user.fullName")

Finally print the person who executed this rule.

On Execution the Rules ran in Sequential manner,


And to notice the Main rule is waiting for all the child jobs to get completed. 

 


After the last child job is completed the Main job status is changed to completed. 


Hope this was useful!!! Happy days on the Cloud!!!


 


No comments:

Post a Comment