Adventures in Groovy – Part 39: First Common Parent
I can’t tell you how many times I have been at a client and they wanted to replicate eliminations at the first common parent like HFM, or some other consolidations system. Maybe there is a good way to do this, but I could never find an efficient and effective way to accomplish it with Essbase calculations. Well, that is history. This is yet another example of how to solve an historically complex problem very simply.
What Is The First Common Parent
Eliminations functionality addresses the posting of inter-company eliminations in scenarios where a full legal consolidation model is not required, such as within a standard financial model. An example would be eliminating sales to another entity inside the organization so the total sales of the organization is not inflating the real sales of the organization. This is typically done at the first node that consolidates the two entities, or first common parent. In the example below, which will be used in the code below, we need to find the first common parent to do the eliminations for entity S253 and S592. The hierarchy below shows that the first parent of these two members is Mountain Division. This is the entity that will calculate and hold the eliminated sales.
Surprisingly Easy With Groovy
The Groovy classes available to us have the ability to query metadata. This allows a calculation to return all kind of things, like the ancestors of members. Groovy takes over the rest by comparing the arrays returned.
For this example, the calculation prompts for two members. In an real-world example, these would likely be defined in the calculation, or maybe with UDAs or attributes. The prompts in this example, C1 and C2, are run time prompts connected to the hierarchy above. Once the members are defined, the next step is to query the ancestors of each of the two members.
First, a connection to the application that has the dimension and members is defined. Once that is done, a dimension object is created that is used to execute the queries. Since we need ancestors, we use IAncestors.
/*RTPS:{C1} {C2}*/ Cube cube = operation.application.getCube("Fin") Dimension companyDim = operation.application.getDimension("Company") List companyOne = companyDim.getEvaluatedMembers("IAncestors(${rtps.C1.toString()})", cube) List companyTwo = companyDim.getEvaluatedMembers("IAncestors(${rtps.C2.toString()})", cube)
companyOne returns an array with the following values.
[S253, AZ_Stores, Mountain_Div, West_Reg, US_Stores, Tot_Company]
companyTwo returns an array with these values.
[S592, MT_Stores, Mountain_Div, West_Reg, US_Stores, Tot_Company]
The hard part, if you consider that hard, is over. Now that the two arrays are defined, a snazzy Groovy method are used. The intersect method will return the common elements of two lists.
The order of the elements returned by the PBCS classes is ordered from the bottom of the hierarchy to the top. The first element would be the first common parent! This example doesn’t illustrate it but this would work for staggered hierarchies just the same.
List commonParents = companyOne.intersect(companyTwo) println "First common parent for ${rtps.C1.toString()} and ${rtps.C2.toString()} is ${commonParents[0]}"
The println results in the following message to the job console.
First common parent for "S253" and "S592" is Mountain_Div
That is it boys and girls. In 6 lines of scripting (and it could be less as some variables are introduced to clearly articulate the process and methods), the first common parent is identified. The most difficult part would be the business logic to accomplish the actual business requirement.
All Done
Now that you know how to get the first common parent, this can be used to dynamically create the appropriate Essbase calculations to provide all the functionality that is needed. If you like this, share it with the community. Post comments if you have any questions. I love getting feedback.
Hi Kyle..
I’m having difficulty with the commonParents List.. In Short, CompanyOne and Company2 populate as expected (just like your blog), but the “commonParents list equates to null, or []. Here’s my log output:
Log messages :
First common parent for “JC_96” and “JC_99” is null
..and here is the contents of all three lists:
List 1: [JC_96, JC_OTHER, TOT_CLASS, CLASS]
LIst 2: [JC_99, JC_LABOR, TOT_CLASS, CLASS]
commonParents: []
The code I’m using for the commonList was is unchanged from your blog.. Thank you for any help you might give on this.. love the blog!
I am wondering if the lists are actually strings. Can you post your entire script?
If I just run what you have in the groovyConsole….it works as well. companyOne = [“JC_96”, “JC_OTHER”, “TOT_CLASS”, “CLASS”] companyTwo = [“JC_99”, “JC_LABOR”, “TOT_CLASS”, “CLASS”]
I run this:
List
List
List commonParents = companyOne.intersect(companyTwo)
I get this
Result: [TOT_CLASS, CLASS]
I would love to get this resolved for you guys. I reran the script in my environment and it still works. I copied from this blog and pasted into a rule.
Hi,
i have this same issue, after intersect i receive null.
If you want to provide your script I can take a look. Even if you copied and pasted, just paste it back in. I ran the rule and it works fine for me, so there must be something different.