Adventures in Groovy – Part 4: Run Time Prompts
Introduction
Groovy provides a very easy way to interact with the user via run time prompts, or RTPs. These can be linked to dimensions, members, and input. One of the huge benefits of getting RTPs in Groovy is that the result can be validated, and the calculation can be cancelled if they don’t validate (we will touch on this in a future post).
The Solution
This is one of the easier things to do with a Groovy calculation. There are two things required. First, the Groovy calculation must prompt the user to select a value. This is done by doing the following.
/*RTPS: {RTP_Consolidate_Data}*/
At any point in the script after the above, the value can be used. If it is going to be used multiple times, it might be easier to set a variable. Regardless of the approach, the value can be referenced using the rtps object as follows.
String sRTP sRTP = rtps.RTP_Consolidate_Data.toString()
That is all that is required!
Conclusion
Beyond the obvious uses of an RTP, I have started using these for a number of other reasons.
- On global forms where multiple values may be changed throughout a short period of time and execute long running calculations, like allocations, I have seen benefits of prompting a user with a yes/no smartlist RTP. If the user has more changes, they may not need to execute the calculation after every save. This gives them the option.
- If there is a requirement where some prompts are dependent on other prompts, using RTPs in Groovy gives you the flexibility to validate the combination. For example, if an employee is set to hourly with a VP title, the prompts can be validated and returned to the user as invalid combinations before the prompts are removed from user view.
I have this in my groovy BR.
String sRTP
sRTP = rtps.UserSL.toString()
I have UserSL as Global RTP
Still I get below error
No Rtp with the name found.
Do you have the following at the top of your rule? It looks like a comment but it is actually embedding the RTP in the rule to be used.
/*RTPS: {UserSL}*/
yes I thought it was comment
after adding that it worked like charm
Thanks a lot
I had the same issue the first time I used it – it is a little confusing :). Glad I could help. If you have multiple RTPs, just put a space between them, like
/*RTPS: {RTP1} {RTP2}*/
Hi Kyle,
Thanks for great blog !
I am trying to use RTP for smartpush and datamap, somehow I am not getting the Department variables RTP and it’s not recognizing. I am able to get RTP for other dimensions. Do you see any issue with this code
/*RTPS: {VarDepartment} */
String sRTP
sRTP = rtps.VarDepartment.toString()
operation.application.getDataMap(“CapexToCapexReporting”).execute(“Department”:sRTP, false)
I believe you need to reference all the RTPs in one line, so I would expect to see something like this in your example: *RTPS: {VarOtherDim1 VarOtherDim2 VarDepartment} */
Thanks for the reply. I did tried that, but Department RTP variable is not recognizing. Do you see any other issue
/*RTPS: {varDepartment} {varEntity} {varSite}*/
String sRTPSEntity
String sRTPSDepartment
String sRTPSSite
sRTPSEntity = rtps.varEntity.toString()
sRTPSDepartment = rtps.varDepartment.toString()
sRTPSSite = rtps.varSite.toString()
operation.application.getDataMap(“FCSTTest”).createSmartPush().execute([“Department”:sRTPSDepartment,”Entity”:sRTPSEntity,”Site”:sRTPSSite])
Thanks
Senthil
Look at https://docs.oracle.com/en/cloud/saas/enterprise-performance-management-common/groov/index.html for more information. I would check to make sure the prompt isn’t hidden in the calculation settings.
Hi Kyle,
I was trying to get the Account members of a web form in the form of RTP, where the user can input the data against the account members on the fly. So, “ACC_Closed_Date” is one such account member. How do I show it in the rtp through groovy ?
I am using the below script –
/*RTPS: {ACC_Closed_Date}*/
def ACC_Closed_Date = rtps.ACC_Closed_Date.member
Can you specify what is the issue in this rule ?
I am getting error –
Unable to retrieve variable ACC_Closed_Date deployed in the application
Did you create your run time prompt yet? You still have to go in and create the RTP in Planning. The scope of it can be app, db, or rule level.
Hi Kyle,
Thanks for this post. I can’t describe what a life savior it is.
If I want to pass level 0 members of a run time prompt of 3 dimensions such as entity, product, region selected by the user to a data map, how can do I so?
I saw your post of passing the level 0 members of the dimension in a loop. But here there are multiple dimensions and they may be parent members. So I want to pass the level 0 of all of them together in the data map
Thanks a ton for your help!
Prashant
I am assuming you want a map with 3 elements and the members of each in one map. In that case, it would look something like this> periodRangeMap = [:]> periodRangeMap = [:]
Map
here you would loop through your RTPs and the member for each in a loop and inside the loop you would have
// Create a place in the map for the dimension if it doesn’t exist
if(periodRangeMap[rtps.rtpXXX.member.dimension.name] == null){periodRangeMap[rtps.rtpXXX.member.dimension.name] = []}
periodRangeMap[dimName] << memberName I have something that loops through a date range and creates a map for each year with the months in the year for the range Date calcStart = Date.parse("yyyy-MMM-dd", "20${rtps.rtpStartYear.getSmartListEntry().getName().toString().substring(2)}-${rtps.rtpStartMonth.getSmartListEntry().getName().toString()}-05") Date calcEnd = Date.parse("yyyy-MMM-dd", "20${rtps.rtpEndYear.getSmartListEntry().getName().toString().substring(2)}-${rtps.rtpEndMonth.getSmartListEntry().getName().toString()}-05") Map
Calendar calendar = Calendar.getInstance();
calendar.setTime(calcEnd);
calendar.add(Calendar.MONTH, 2)
Date loopEnd = calendar.getTime()
while (current.before(loopEnd)) {
calendar.setTime(current);
periodRange << [current.format("MMM"),"FY${current.format("YY")}"] if(periodRangeMap["FY${current.format("YY")}".toString()] == null){periodRangeMap["FY${current.format("YY")}".toString()] = []} periodRangeMap["FY${current.format("YY")}".toString()] << current.format("MMM").toString() periodSubmitYears << "FY${current.format("YY")}".toString() periodSubmitPeriods << current.format("MMM").toString() calendar.add(Calendar.MONTH, 1); current = calendar.getTime(); } Hope this helps.
Hi Kyle, is it possible to pass a value of a string to a hidden RTP when a business rule executes using groovy?
I am creating dynamic members-on-the-fly for a standard planner and have managed to create a unique member name (to add), using a concatenation of customer (from the POV), date and time. I cannot seem to pass this string to the RTP, to effectively override what the user would normally enter themselves.
If I could get it to work in this way, then a standard planner can automatically create a member to be used on a form. The issue with using the ‘saveMember’ method is that it is only available to Administrators as a privileged method.
Thanks
Dermott
Why do you need the RTP if you are dynamically creating the member? As far as adding the member, you can use dynamic children. I don’t like that honestly. What I have done is to have an admin rule run at night (scheduled) that takes all the newly created members and create new members in the outline. So the test member that holds the new member would be used to create the member. In your case, I don’t know if you actually need to create the dynamic member name when the user creates the action since it is build on a POV and date. The rule creates the new member, does the refresh, then runs a rule that moves the data from the TBH member to the created member based on the text value, just like when you created the member.
Hope that helps.
I had an issue where I was using save.Member method to create the dynamic member. I should have been using the addDynamicChild method/function.
// Constructs the promotion string details
String nextPromo = ‘”‘ + “Promo_” + sCustomer + “_” + date.format(‘yyyyMMdd’) + “_” + date.format(‘HHmmss’) + ‘”‘
// Adds the member to the outline
Member promotion = DriverMem.addDynamicChild(nextPromo)
What was so hard to figure out, now looks so easy…
Thanks for your help 🙂
Can I check RTP within an IF loop in Groovy scripting.
Example : If(RTP == ABC)
( Statement1);
Elseif(RTP == DEF)
(Statement2);
Else(RTP == GHI)
(Statement3);
ENDIF