SlideShare a Scribd company logo
1 of 54
Download to read offline
Groovy Grid Builder – Deep Dive • Kyle Goodfriend
LAST MINUTE ODTUG KSCOPE18
PLANNING SOUVENIRS
June 14th
, 9:30 - 11:00 a.m.
Southern Hemisphere II, Fifth Level
Kyle Goodfriend
ODTUG • Kscope 18
2
GROOVY GRIDBUILDER DEEP DIVE AGENDA
INTRODUCTION
PBCS AND GROOVY
THE GRIDBUILDER
GRIDBUILDER
METHODS
REAL WORLD
EXAMPLES
PRODUCTIVITY GUIDANCE
AND SUGGESTIONS
WHERE TO GO NEXT
WRAP-UP
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
INTRODUCTION
3Groovy Grid Builder – Deep Dive • Kyle Goodfriend
ODTUG • Kscope 18
1
Slide 4
HOUSEKEEPING
• Questions and Answers
» We will answer questions throughout
the presentation
» Bring questions with your
name/email/phone number up to the
front at the end of the presentation and I
will make sure they get answered
ODTUG • KScope18
Top-Down & Bottom-Up Planning at Breakthru Beverage Group
Wed, Jun 13, 2018 (11:45 PM - 12:45 PM)
5
WHO AM I?
• BBA, concentration in Finance
• Moved into technology because I was always trying
to find a way to eliminate redundant tasks (AKA –
hated my job)
• Started using Essbase to consolidate multiple GLs
with consolidated companies
• Started consulting in 1999
• Really enjoy what I do because it is artistic and
creative - finding solutions for complex problems
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
kyle@in2hyperion.com
614.668.7324
6
WHY DID I START USING GROOVY CALCULATIONS?
• Forms were taking minutes to update
» Hundreds of products
» Data was entered at parent level
» Hundreds of allocations were executed
• Client wanted real time reporting
» Users wanted full P&L consolidated reporting when product/material
group/delivery channel were made
» Users wanted full P&L consolidated reporting when employee level changes were
made
• Complex data validation was required in data that was changed
» Monthly spreading has to have a net impact of zero
» Employee level validation was required
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
PERFORMANCE AND USABILITY
7
99%IMPROVEMENT 98% 99%
Reporting includes all updates from
detailed modules (product, Capex,
workforce, and similar modules) and
is included in
real time as changes are made
Consolidated Reporting
Reporting includes all updates from
detailed modules (product, Capex,
workforce, and similar modules) at
scheduled intervals
users have to wait to see
consolidated information
Groovy eliminates the need to
consolidate the BSO cube and
copies data directly from the
ASO cube at a consolidated
level
.2 Seconds
Dimensions are consolidated
and copied to the P&L model
82.9 Seconds
Consolidated P&L
Product detailed dimensions
are consolidated and moved
to the P&L model
Groovy selects only the cells
that where edited and copies
only what changed to the
reporting model
1.0 Seconds
All data on the form is
synchronized
14.5 Seconds
Smart Push
Data synchronizes to the
reporting cube for analysis
01
0110
0001
01101
Groovy selects only edited
cells and executes the logic
on only products and periods
that changed
0.3 Seconds
All products on the form are
calculated
26.1 Seconds
Business Logic
Growth rates are entered at
total product breakouts and
allocated to the detailed level
With the inclusion of Groovy
and access to the Java API,
more customization can be
integrated to maximum
performance and achieve real
time consolidated reporting
Submit
Planner Input
User submits updates to the
Gross Profit model at a
detailed product level that
exists at a more granular level
than in the P&L model
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
ADMINISTRATIVE FLEXIBILITY
8
Reporting includes all updates from
detailed modules (product, Capex,
workforce, and similar modules) and
is included in
real time as changes are made
Consolidated Reporting
Reporting includes all updates from
detailed modules (product, Capex,
workforce, and similar modules) at
scheduled intervals
users have to wait to see
consolidated information
Automated Process
Administrative processes are
executed to run all business
logic and model
synchronizations
The entire data set is
consolidated and moved to
the P&L model
12.0 Seconds
Dimensions are consolidated
and copied to the P&L model
663.6 Seconds
Global Consolidation
Global product consolidations are
often required to catch all changes
and completed during
maintenance windows
99% 99%
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
NEVER THOUGHT I WOULD SAY
THIS
It is possible to build a planning application without writing a single BSO calculation
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend 9
PBCS AND GROOVY
Groovy is now available in ePBCS as calculation
10Groovy Grid Builder – Deep Dive • Kyle Goodfriend
ODTUG • Kscope 18
2
11
CONVERTING TO GROOVY CALCULATION
• Open Rules in PBCS and create a new rule
• Change the dropdown box with from Designer to Edit Script
• Change the Script type dropdown box to Groovy Script
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
12
WHAT IS AVAILABLE WITH GROOVY CALCULATIONS
• Iterating through data grid cells
» Color coding
» Data validation
» Identification of edited and non-edited cells
• Data synchronization between ASO/BSO and BSO/ASO
• Execute business logic
• Mapping data between cubes
• Can be executed in stages
» Pre-save
» On-load
» Post-save
Groovy Grid Builder – Deep Dive • Kyle GoodfriendODTUG • Kscope 18
THE GRID BUILDER
The GridBuilder methods provide a completely
customized way to do so many things. Your
creativity is the only thing that limits the
possibilities. It is the gateway to completing the
circle of doing everything in Groovy
ODTUG • Kscope 18
Groovy Grid Builder – Deep Dive • Kyle Goodfriend 13
3
Groovy Grid Builder – Deep Dive • Kyle Goodfriend 14
GRIDBUILDER CONCEPTS
• Each grid has
» A POV
» Column headers
» Row headers
• Grids can
» Build = refresh
» Save = submit
• Grids have limits
» 500,000 cell limit when reading
» 200,000 cell limit when saving
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
Groovy Grid Builder – Deep Dive • Kyle GoodfriendODTUG • Kscope 18 15
GRIDBUILDER USE CASES
• Benefits
» Move Data from ASO to BSO to eliminate the need for consolidations
» Calculate outside of Essbase
» If the DataMap is used it bypases user security
• Creative use cases
» Mapping data when moving from cube to cube
» Clearing ASO without limits – Data Maps only clear what is in the BSO cube, not
everything in the POV
» Get POV with data (aka, suppression)
Groovy Grid Builder – Deep Dive • Kyle Goodfriend
GRIDBUILDER
METHODS
Before you can become productive, get to know
the methods.
16Groovy Grid Builder – Deep Dive • Kyle Goodfriend
ODTUG • Kscope 18
4
Groovy Grid Builder – Deep Dive • Kyle Goodfriend 17
GRID BUILDER CLASS OVERVIEW
• Classes
» DataGridBuilder (submit data)
» DataGridDefinitionBuilder (read data)
• DataGridBuilder
» Create a grid
» Specify data
» Save the data
• DataGridDefinitionBuilder
» Create a grid
» Retrieve the data
» Can use functions
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
Groovy Grid Builder – Deep Dive • Kyle Goodfriend 18
GRIDBUILDER METHODS
• DataGridBuilder
» addColumn
» addPov
» addRow
» build
» saveGrid (submit)
• DataGridDefinitionBuilder
» addColumn
» addPov
» addRow
» setSuppressMissingBlocks
» Build (refresh)
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
19
DATAGRIDBUILDER EXAMPLE
// Setup the connection to the plan type
Cube cube = operation.application.getCube("Plan1")
DataGridBuilder builder = cube.getDataGridBuilder("MM/DD/YYYY")
// Setup the grid POV, Rows, and Columns
builder.addPov('Salary', 'Current', 'Local', 'BU Version_1’)
builder.addColumn('FY16', 'FY16', 'FY16’)
builder.addColumn('Jan', 'Feb', 'Mar’)
// Add rows to the grid
builder.addRow(['Department 1', 'Employee 1'], [30000, 30000, 30000])
builder.addRow(['Department 5', 'Employee 2'], [40000, 40000, 40000])
builder.addRow(['Department 1', 'Employee 3'], [30000, 30000, 30000])
// Create a status class to hold the results
DataGridBuilder.Status status = new DataGridBuilder.Status()
// Build the grid – basically a refresh/retrieve
DataGrid grid = builder.build(status)
println("Total number of cells accepted: status.numAcceptedCells")
println("Total number of cells rejected: status.numRejectedCells")
println("First 100 rejected cells: status.cellsRejected")
// Save the data to the cube
cube.saveGrid(grid)
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
20
DATAGRIDDEFINITIONBUILDER EXAMPLE
// Setup the connection to the plan type
Cube cube = operation.application.getCube("Plan1")
//Create the grid definition builder
DataGridDefinitionBuilder builder = cube.dataGridDefinitionBuilder
// Add the POV – Dimensions and a collection of the members in those dimensions
builder.addPov(['Years', 'Scenario', 'Currency', 'Period', 'Version', 'Entity’],
[['FY16'], ['Current'], ['Local'], ['BegBalance'], ['BU Version_1'], ['No Entity’]])
// Add the columns – 2 parameters, collection of dimensions and
// collection of collections of members in those dimensions
builder.addColumn(['Years', 'Account’],
[['Children(Years)'],['Min Salary','Max Salary','Min Bonus','Max Bonus']])
// Add rows no data - in this class as it is retrieving data
builder.addRow(['Grades'], [ ['ILvl0Descendants("Grades")']])
// Build the grid
DataGridDefinition gridDefinition = builder.build()
// Load a data grid from the specified grid definition and cube
DataGrid dataGrid = cube.loadGrid(gridDefinition, false)
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
REAL WORLD
EXAMPLES
A walk through gridbuilder use cases
ODTUG • Kscope 18
Groovy Grid Builder – Deep Dive • Kyle Goodfriend 21
5
22
DEMONSTRATION
CLEAR ASO DATA
• DataMaps won’t work when removing
data in the BSO application first
» Removing TBHs
» Removing new products
• Clearing data when the Smart Push
clear limits are reached
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
23
SCRIPT SETUP
/*RTPS: {RTP_YesNoClearBlk} {RTP_Vendor}*/
def mbUs = messageBundle(["validation.AbortClear":"You have chosen to NOT clear the selected Brand Family. No Action
has been taken. To proceed with clearing, please acknowledge by selecting (YES) from the drop down menu. Otherwise
please click (Cancel). "])
def mbl = messageBundleLoader(["en" : mbUs])
//If yes, proceed to second rule in rule set
if(rtps.RTP_YesNoClearBlk.getEssbaseValue() != "1")
{
println rtps.RTP_YesNoClearBlk.getEssbaseValue()
println "The user cancelled the operation"
throwVetoException(mbl, "validation.AbortClear", rtps.RTP_YesNoClearBlk)
}
//set account map
def acctMap = ['Regular_Cases':'Regular_Cases',
'Net_Sales':'42001',
'Cost_of_Sales_without_Samples':'50001',
'Gallonage_Tax':'50015',
'Depletion_Allowance_Manual_Chargeback':'56010',
'Gain_Loss_Inv_Reval':'50010',
'Supplier_Commitments':'56055',
'Supplier_Spend_Non_Committed':'56300',
'Samples':'56092'
]
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
24
GETTING THE POV
// Get POV
String sCompany = operation.grid.getCellWithMembers().getMemberName("Company")
String sMaterialGroup =
operation.grid.getCellWithMembers().getMemberName("Material_Group")
String sChannel = operation.grid.getCellWithMembers().getMemberName("Channel")
String sVendor = rtps.RTP_Vendor.getMember()
//operation.grid.getCellWithMembers().getMemberName("Vendor")
String sSource = operation.grid.getCellWithMembers().getMemberName("Source")
String sVersion = operation.grid.getCellWithMembers().getMemberName("Version")
String sScenario = operation.grid.getCellWithMembers().getMemberName("Scenario")
String sYear = operation.grid.getCellWithMembers().getMemberName("Years")
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
25
USING THE GRIDBUILDER TO CLEAR THE DATA
//Fin Grid Setup
Cube rGPCube = operation.application.getCube("rGP")
DataGridBuilder rGPGrid = rGPCube.dataGridBuilder("MM/DD/YYYY")
rGPGrid.addPov(sYear,sScenario,'OEP_Working',sCompany,
sMaterialGroup,sChannel,sVendor,sSource,'MTD’)
// Clear the accounts in the account map
rGPGrid.addColumn('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug’,
'Sep','Oct','Nov','Dec’)
acctMap.eachWithIndex { AcctItem , i ->
rGPGrid.addRow([AcctItem.key,'Local'],[0,0,0,0,0,0,0,0,0,0,0,0])
rGPGrid.addRow([AcctItem.key,'USD'],[0,0,0,0,0,0,0,0,0,0,0,0])
}
// Clear additional input accounts
def
OtherAccounts = ['GP_Level 1','GP_Level 2','Avg Price/ Case Inp','GP Level 1 & Inp','GP Level 2 % Inp'].each{
rGPGrid.addRow([it,'local'],[0,0,0,0,0,0,0,0,0,0,0,0])
rGPGrid.addRow([it,'USD'],[0,0,0,0,0,0,0,0,0,0,0,0])
}
DataGridBuilder.Status rstatus = new DataGridBuilder.Status()
DataGrid rgrid = rGPGrid.build(rstatus)
println("Total number of cells accepted: $rstatus.numAcceptedCells")
println("Total number of cells rejected: $rstatus.numRejectedCells")
println("First 100 rejected cells: $rstatus.cellsRejected")
rGPCube.saveGrid(rgrid)
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
26
DEMONSTRATION
REAL-TIME
REPORTING
• Move data to ASO without
consolidations
• Map data between different accounts
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
27
PERFORMANCE AND PROCESS
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
99%IMPROVEMENT 98% 99%
Reporting includes all updates from
detailed modules (product, Capex,
workforce, and similar modules) and
is included in
real time as changes are made
Consolidated Reporting
Reporting includes all updates from
detailed modules (product, Capex,
workforce, and similar modules) at
scheduled intervals
users have to wait to see
consolidated information
Groovy eliminates the need to
consolidate the BSO cube and
copies data directly from the
ASO cube at a consolidated
level
.2 Seconds
Dimensions are consolidated
and copied to the P&L model
82.9 Seconds
Consolidated P&L
Product detailed dimensions
are consolidated and moved
to the P&L model
Groovy selects only the cells
that where edited and copies
only what changed to the
reporting model
1.0 Seconds
All data on the form is
synchronized
14.5 Seconds
Smart Push
Data synchronizes to the
reporting cube for analysis
01
0110
0001
01101
Groovy selects only edited
cells and executes the logic
on only products and periods
that changed
0.3 Seconds
All products on the form are
calculated
26.1 Seconds
Business Logic
Growth rates are entered at
total product breakouts and
allocated to the detailed level
With the inclusion of Groovy
and access to the Java API,
more customization can be
integrated to maximum
performance and achieve real
time consolidated reporting
Submit
Planner Input
User submits updates to the
Gross Profit model at a
detailed product level that
exists at a more granular level
than in the P&L model
28
TYPICAL CONSOLIDATION VS GRIDBUILDER
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
Detailed
App
Consolidated
P&L
Detailed
App
Consolidated
P&L
NON GROOVY
• All dimensions need to be
consolidated
• Movement from ASO is not possible
• Movement is batched and scheduled
WITH GROOVY
• NO BSO consolidation is required
• Data can be transferred from ASO
• Movement is executed on form
save
29
SETTING UP THE VARIABLES AND PUSHING DATA
def startTime = currentTimeMillis()
def procTime = currentTimeMillis()
def elapsed=(currentTimeMillis()-startTime)/1000
Calendar calendar = Calendar.getInstance()
calendar.setTimeInMillis(currentTimeMillis())
def now = calendar.getTime()
def dtstmp = now.format("MM/dd/yyyy")
elapsed=(currentTimeMillis()-procTime)/1000
procTime = currentTimeMillis()
println "****************************************************"
println "Time taken for allocation and consolidation = $elapsed secs"
println "Total Time = " + (currentTimeMillis()-startTime)/1000 + " secs"
println "****************************************************"
//****************************************************************************
// Data Movement between Apps
//****************************************************************************
// Get POV
String sCompany = operation.grid.getCellWithMembers().getMemberName("Company")
def sMaterialGroup = operation.grid.getCellWithMembers().getMemberName("Material_Group")
String sChannel = operation.grid.getCellWithMembers().getMemberName("Channel")
// Get a list of edited rows
def lstVendors = []
operation.grid.dataCellIterator({DataCell cell -> cell.edited}).each{
lstVendors.add(it.getMemberName("Vendor"))
}
String strVendors = """"${lstVendors.unique().join('","')}""""
println "data push running for " + strVendors
if(operation.grid.hasSmartPush("GP_SmartPush") && lstVendors)
operation.grid.getSmartPush("GP_SmartPush").execute(["Vendor":strVendors,"Currency":'"Local","USD”’])
elapsed=(currentTimeMillis()-procTime)/1000
procTime = currentTimeMillis()
println "****************************************************"
println "Time taken for data push = $elapsed secs"
println "Total Time = " + (currentTimeMillis()-startTime)/1000 + " secs"
println "****************************************************"
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
30
CREATING THE READER GRID
//set account map
def acctMap = ['Regular_Cases':'Regular_Cases',
'Net_Sales':'42001',
'Cost_of_Sales_without_Samples':'50001',
'Gallonage_Tax':'50015',
'Depletion_Allowance_Manual_Chargeback':'56010',
'Gain_Loss_Inv_Reval':'50010',
'Supplier_Commitments':'56055',
'Supplier_Spend_Non_Committed':'56300',
'Samples':'56092',
'GP_NDF':'56230',
'GP_BDF':'56200',
'GP_Contract_Amortization':'56205',
'Sample_Adjustment':'56090'
]
Cube lookupCube = operation.application.getCube("rGP")
DataGridDefinitionBuilder builder = lookupCube.dataGridDefinitionBuilder()
builder.addPov(['Years', 'Scenario', 'Version', 'Company','Channel','Material_Group','Source','Vendor','View'], [['&v_PlanYear'], ['OEP_Plan’],
['OEP_Working'], [sCompany],['Tot_Channel'],['Total_Material_Group'],['Tot_Source'],['Tot_Vendor'],['MTD']])
builder.addColumn(['Period','Currency'], [ ['ILvl0Descendants("YearTotal")'],['Local','USD'] ])
for ( e in acctMap ) {
builder.addRow(['Account'], [ [e.key] ])
}
DataGridDefinition gridDefinition = builder.build()
// Load the data grid from the lookup cube
DataGrid dataGrid = lookupCube.loadGrid(gridDefinition, false)
def povmbrs = dataGrid.pov
println "POV:"
println povmbrs*.essbaseMbrName
def rowmbrs = dataGrid.rows
println"ROWS HEADER:"
println rowmbrs.headers*.essbaseMbrName
def colmbrs = dataGrid.columns
println"COLUMNS:"
println colmbrs[0]*.essbaseMbrName
println colmbrs[1]*.essbaseMbrName
def tmpColMbrs = []
//colmbrs[0].each{println it.essbaseMbrName}
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
31
CREATING THE SUBMISSION FORMS
//Fin Grid Setup
Cube finCube = operation.application.getCube("Fin")
Cube rfinCube = operation.application.getCube("rFin")
DataGridBuilder finGrid = finCube.dataGridBuilder("MM/DD/YYYY")
DataGridBuilder rfinGrid = rfinCube.dataGridBuilder("MM/DD/YYYY")
finGrid.addPov('&v_PlanYear','OEP_Plan','OEP_Working',sCompany,'No_Center','GP_Model')
rfinGrid.addPov('&v_PlanYear','OEP_Plan','OEP_Working',sCompany,'No_Center','GP_Model','MTD')
def colnames = colmbrs[0]*.essbaseMbrName
def colnames1 = colmbrs[1]*.essbaseMbrName
String scolmbrs = "'" + colnames.join("', '") + "'"
finGrid.addColumn(colmbrs[0]*.essbaseMbrName as String[])
rfinGrid.addColumn(colmbrs[0]*.essbaseMbrName as String[])
finGrid.addColumn(colmbrs[1]*.essbaseMbrName as String[])
rfinGrid.addColumn(colmbrs[1]*.essbaseMbrName as String[])
def lstCurrency = ["Local","USD"]
def UniqueMonths = colnames.unique()
def iCurrencyCount = 0
dataGrid.dataCellIterator('Jan','Local').each{ it ->
def sAcct = "${acctMap.get(it.getMemberName('Account'))}"
def sValues = []
List addcells = new ArrayList()
UniqueMonths.each{cMonth ->
lstCurrency.each{cCurrency ->
sValues.add(it.crossDimCell(cMonth.toString(),cCurrency.toString()).data)
addcells << it.crossDimCell(cMonth.toString(),cCurrency.toString()).data
//println cMonth.essbaseMbrName + cCurrency.toString()
}
}
finGrid.addRow([acctMap.get(it.getMemberName('Account'))],addcells)
rfinGrid.addRow([acctMap.get(it.getMemberName('Account'))],addcells)
println "${acctMap.get(it.getMemberName('Account'))}" + "," + sValues.join(",")
}
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
32
EXECUTING THE SUBMISSION FORMS
DataGridBuilder.Status status = new DataGridBuilder.Status()
DataGridBuilder.Status rstatus = new DataGridBuilder.Status()
DataGrid grid = finGrid.build(status)
DataGrid rgrid = rfinGrid.build(rstatus)
println("Total number of cells accepted: $status.numAcceptedCells")
println("Total number of cells rejected: $status.numRejectedCells")
println("First 100 rejected cells: $status.cellsRejected")
finCube.saveGrid(grid)
println("Total number of cells accepted: $rstatus.numAcceptedCells")
println("Total number of cells rejected: $rstatus.numRejectedCells")
println("First 100 rejected cells: $rstatus.cellsRejected")
rfinCube.saveGrid(rgrid)
elapsed=(currentTimeMillis()-procTime)/1000
procTime = currentTimeMillis()
println "****************************************************"
println "Time taken copy to fin = $elapsed secs"
println "Total Time = " + (currentTimeMillis()-startTime)/1000 + " secs"
println "****************************************************"
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
33
DEMONSTRATION
CALCULATING
OUTSIDE OF THE
ESSBASE ENGINE
• Calculating Currency in ASO
• Connecting forms with business logic
directly to an ASO play type
» Rewrite form rate*volume or currency
conversion
» NBF calculate accounts
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
SETTING UP THE POV
// define common functions
def checkZero(double dVal=0) {
if(dVal == 0) {
return 1
}
else {
return dVal
}
}
boolean convertCurrency(def account='')
{
Dimension AccountDim = operation.application.getDimension("Account")
Member AccountMbr = AccountDim.getMember(account)
def memberProps = AccountMbr.toMap()
if(memberProps['UDA'].toString().contains('IgnoreCurrencyConversion'))
return false
else
return true
}
//set account map
%Script(name:="GP - Account Map",application:="BreakFin",plantype:="GP")
// POV
String sCompany = operation.grid.getCellWithMembers().getMemberName("Company")
String sVersion = operation.grid.getCellWithMembers().getMemberName("Version")
String sScenario = operation.grid.getCellWithMembers().getMemberName("Scenario")
String sYear = operation.grid.getCellWithMembers().getMemberName("Years")
String sMaterialGroup = operation.grid.getCellWithMembers().getMemberName("Material_Group")
String sChannel = operation.grid.getCellWithMembers().getMemberName("Channel")
String sSource = operation.grid.getCellWithMembers().getMemberName("Source")
def currencyRates = [:]
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
def acctMap = ['Regular_Cases':'Regular_Cases',
'Net_Sales':'42001',
'Cost_of_Sales_without_Samples':'50001',
'Gallonage_Tax':'50015',
'Depletion_Allowance_Manual_Chargeback':'56010',
'Gain_Loss_Inv_Reval':'50010',
'Supplier_Commitments':'56055',
'Supplier_Spend_Non_Committed':'56300',
'Samples':'56092'
]
35
CREATE THE CURRENCY RATES MAP
// Build currency for the company
Cube lookupCube = operation.application.getCube("GP")
DataGridDefinitionBuilder builder = lookupCube.dataGridDefinitionBuilder()
builder.addPov(['Years', 'Scenario',
'Version','Channel','Material_Group','Source','Vendor’,
'Currency','Account’],
[[sYear],[sScenario],[sVersion],['No_Channel'],['No_Material_Group’],
['Input'],['No_Vendor_Assigned'],['Local'],['End_C_Rate']])
builder.addColumn(['Period'], [ ['ILvl0Descendants("YearTotal")']])
builder.addRow(['Company'], [ [sCompany] ])
DataGridDefinition gridDefinition = builder.build()
// Load the data grid from the lookup cube
lookupCube.loadGrid(gridDefinition, false).withCloseable { dataGrid ->
dataGrid.dataCellIterator().each{ rate ->
currencyRates.put(rate.getMemberName('Period'),checkZero(rate.data))
}
}
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
36
SETUP THE WRITEBACK GRID BUILDERS
// Setup Grid to submit results
// Get list of vendors
def listVendors = operation.grid.rows.headers*.essbaseMbrName.collect
{vendor, account -> return vendor}.unique()
// List of calculated members
def listAccounts = ["Regular_Cases","Net_Sales","GP_Level_1","Cost_of_Sales_without_Samples",
"GP_Level_2","Depletion_Allowance_Manual_Chargeback"]
//Fin Grid Setup
Cube finCube = operation.application.getCube("GP")
Cube rfinCube = operation.application.getCube("rGP")
DataGridBuilder bsoGrid = finCube.dataGridBuilder("MM/DD/YYYY")
DataGridBuilder aspGrid = rfinCube.dataGridBuilder("MM/DD/YYYY")
bsoGrid.addPov(sYear,sScenario,sVersion,sChannel,sMaterialGroup,sSource,sCompany)
aspGrid.addPov(sYear,sScenario,sVersion,sChannel,sMaterialGroup,sSource,sCompany,'MTD')
bsoGrid.addColumn('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')
aspGrid.addColumn('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')
def lstCurrency = ["Local","USD"]
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
37
ADD THE ROWS AND VALUES TO SUBMIT (PART 1)
// loop through the grid on the form
listVendors.each{ vendor ->
listAccounts.each{ account ->
def sValues = []
def sValuesUSD = []
List addcells = new ArrayList()
List addcellsUSD = new ArrayList()
['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'].each{cMonth ->
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
38
ADD THE ROWS AND VALUES TO SUBMIT (PART 2)
double setValue
switch (account) {
case "Net_Sales":
setValue = operation.grid.getCellWithMembers("Avg_Price/Case_Inp",cMonth.toString(),vendor.toString()).data *
operation.grid.getCellWithMembers("Regular_Cases",cMonth.toString(),vendor.toString()).data
break
case "GP_Level_1":
double netSales = operation.grid.getCellWithMembers("Avg_Price/Case_Inp",cMonth.toString(),vendor.toString()).data *
operation.grid.getCellWithMembers("Regular_Cases",cMonth.toString(),vendor.toString()).data
setValue = netSales * operation.grid.getCellWithMembers("GP_1_%_Inp",cMonth.toString(),vendor.toString()).data
break
case "Cost_of_Sales_without_Samples":
double netSales = operation.grid.getCellWithMembers("Avg_Price/Case_Inp",cMonth.toString(),vendor.toString()).data *
operation.grid.getCellWithMembers("Regular_Cases",cMonth.toString(),vendor.toString()).data
double gp1 = netSales * operation.grid.getCellWithMembers("GP_1_%_Inp",cMonth.toString(),vendor.toString()).data
setValue = netSales - gp1
break
case "GP_Level_2":
double netSales = operation.grid.getCellWithMembers("Avg_Price/Case_Inp",cMonth.toString(),vendor.toString()).data *
operation.grid.getCellWithMembers("Regular_Cases",cMonth.toString(),vendor.toString()).data
setValue = netSales * operation.grid.getCellWithMembers("GP_2_%_Inp",cMonth.toString(),vendor.toString()).data
break
case "Depletion_Allowance_Manual_Chargeback":
double netSales = operation.grid.getCellWithMembers("Avg_Price/Case_Inp",cMonth.toString(),vendor.toString()).data *
operation.grid.getCellWithMembers("Regular_Cases",cMonth.toString(),vendor.toString()).data
double gp1 = netSales * operation.grid.getCellWithMembers("GP_1_%_Inp",cMonth.toString(),vendor.toString()).data
double gp2 = netSales * operation.grid.getCellWithMembers("GP_2_%_Inp",cMonth.toString(),vendor.toString()).data
setValue = netSales - gp1
break
default:
setValue = operation.grid.getCellWithMembers(account.toString(),cMonth.toString(),vendor.toString()).data
break
}
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
39
ADD THE ROWS AND VALUES TO SUBMIT (PART 3)
sValues.add(setValue)
addcells << setValue
// Convert Currency if account should be converted
if(convertCurrency(account)){
sValuesUSD.add(currencyRates[cMonth].toString().toDouble() * setValue)
addcellsUSD << currencyRates[cMonth].toString().toDouble() * setValue
}
else
{
sValuesUSD.add(setValue)
addcellsUSD << setValue
}
}
bsoGrid.addRow([account.toString(),vendor.toString(),'Local'],addcells)
bsoGrid.addRow([account.toString(),vendor.toString(),'USD'],addcellsUSD)
aspGrid.addRow([account.toString(),vendor.toString(),'Local'],addcells)
aspGrid.addRow([account.toString(),vendor.toString(),'USD'],addcellsUSD)
println account + ' ' + vendor + ' Local:' + addcells
println account + ' ' + vendor + ' USD:' + addcellsUSD
}
}
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
40
SUBMIT AND GET THE STATUS OF THE GRID BUILDER
DataGridBuilder.Status status = new DataGridBuilder.Status()
DataGridBuilder.Status rstatus = new DataGridBuilder.Status()
DataGrid grid = bsoGrid.build(status)
DataGrid rgrid = aspGrid.build(rstatus)
println("Total number of cells accepted: $status.numAcceptedCells")
println("Total number of cells rejected: $status.numRejectedCells")
println("First 100 rejected cells: $status.cellsRejected")
finCube.saveGrid(grid)
println("Total number of cells accepted: $rstatus.numAcceptedCells")
println("Total number of cells rejected: $rstatus.numRejectedCells")
println("First 100 rejected cells: $rstatus.cellsRejected")
rfinCube.saveGrid(rgrid)
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
41
CHECK OUT THE RETURN LOG CREATED
Log messages :
*** data validation for the grid
Regular_Cases NBF1 Local:[3.0, 2.0, 2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Regular_Cases NBF1 USD:[3.0, 2.0, 2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Net_Sales NBF1 Local:[39.0, 126.0, 44.0, 4.0, 10.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Net_Sales NBF1 USD:[39.0, 12.600000000000001, 8.8, 1.2000000000000002, 4.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
GP_Level_1 NBF1 Local:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
GP_Level_1 NBF1 USD:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Cost_of_Sales_without_Samples NBF1 Local:[39.0, 126.0, 44.0, 4.0, 10.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Cost_of_Sales_without_Samples NBF1 USD:[39.0, 12.600000000000001, 8.8, 1.2000000000000002, 4.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
GP_Level_2 NBF1 Local:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
GP_Level_2 NBF1 USD:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Depletion_Allowance_Manual_Chargeback NBF1 Local:[39.0, 126.0, 44.0, 4.0, 10.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Depletion_Allowance_Manual_Chargeback NBF1 USD:[39.0, 12.600000000000001, 8.8, 1.2000000000000002, 4.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Regular_Cases NBF2 Local:[33.0, 32.0, 33.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Regular_Cases NBF2 USD:[33.0, 32.0, 33.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Net_Sales NBF2 Local:[1452.0, 1056.0, 1089.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Net_Sales NBF2 USD:[1452.0, 105.60000000000001, 217.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
GP_Level_1 NBF2 Local:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
GP_Level_1 NBF2 USD:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Cost_of_Sales_without_Samples NBF2 Local:[1452.0, 1056.0, 1089.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Cost_of_Sales_without_Samples NBF2 USD:[1452.0, 105.60000000000001, 217.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
GP_Level_2 NBF2 Local:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
GP_Level_2 NBF2 USD:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Depletion_Allowance_Manual_Chargeback NBF2 Local:[1452.0, 1056.0, 1089.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Depletion_Allowance_Manual_Chargeback NBF2 USD:[1452.0, 105.60000000000001, 217.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
*** status
Total number of cells accepted: 288
Total number of cells rejected: 0
First 100 rejected cells: []
Total number of cells accepted: 288
Total number of cells rejected: 0
First 100 rejected cells: []
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
42
DEMONSTRATION
QUERYING
METADATA
• Process Segmentation
» Execute processes only on a POV with
data
» Loop through metadata and execute
processes
• Currency Conversion
» Identify whether the account should be
converted to USD
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
43
PROCESS SEGMENTATION
Cube cube = operation.application.getCube("GP")
Dimension companyDim = operation.application.getDimension("Company", cube)
def Companies = companyDim.getEvaluatedMembers("ILvl0Descendants(tot_Company)", cube) as String[]
def Currencies = ["Local","USD"]
// Companies.each{company->
for (def i = 0; i < Companies.size(); i++) {
def sCompanyItem = '"' + Companies[i] + ‘”’
// Currencies.each(currency ->
for (def iCurrency = 0; iCurrency < Currencies.size(); iCurrency++){
def sCurrency = '"' + Currencies[iCurrency] + '"'
operation.application.getDataMap("GP Form Push").execute
(["Company":Companies[i],"Channel":"ILvl0Descendants(Channel)",
"Material_Group":"ILvl0Descendants(Material_Group)",
"Vendor":"ILvl0Descendants(Vendor)","Scenario":rtps.RTP_Scenario.getEssbaseValue(),
"Version":"OEP_Working","Years":rtps.RTP_Year.getEssbaseValue(),
"Source":"ILvl0Descendants(Source)","Currency":Currencies[iCurrency]],
rtps.RTP_Push.getEssbaseValue().toBoolean())
elapsed=(currentTimeMillis()-procTime)/1000
procTime = currentTimeMillis()
println "Push for Company $sCompanyItem, in ${Currencies[iCurrency]}: $elapsed seconds"
}
}
elapsed=(currentTimeMillis()-procTime)/1000
procTime = currentTimeMillis()
println "****************************************************"
println "Time taken for allocation and consolidation = $elapsed secs"
println "Total Time = " + (currentTimeMillis()-startTime)/1000 + " secs"
println "****************************************************"
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
44
CURRENCY CONVERSION
boolean convertCurrency(def account='')
{
Dimension AccountDim = operation.application.getDimension("Account")
Member AccountMbr = AccountDim.getMember(account)
def memberProps = AccountMbr.toMap()
if(memberProps['UDA'].toString().contains('IgnoreCurrencyConversion'))
return false
else
return true
}
if(convertCurrency(account)){
[… do some action and convert the account (revenue * currency conversion rate)]
}
else{
[… do some action but don’t convert the account (headcount)]
}
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
PRODUCTIVITY,
GUIDANCE AND
SUGGESTIONS
Many people have challenges learning Groovy and
the PBCS API at the same time. Here are some
things that might help you get started
ODTUG • Kscope 18
Groovy Grid Builder – Deep Dive • Kyle Goodfriend 45
6
46
SUGGESTIONS / TIPS
• Get to know maps/collections/lists and how to manipulate them
• Learn the inheritance of objects and how Groovy works with them
• Understand how to read the API
• Use closures anywhere you can
• Grow your knowledge around string manipulation
• Come up with a strategy to log the grid POV/headers/columns/data
• .crossDimCell is your best friend
I plan on posting detailed explainations of these at www.in2Hyperion.com
in the near future, along with other use cases around Groovy knowledge
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
WHERE TO GO NEXT
Need help? Here is a great place to start.
47
ODTUG • Kscope 18
Groovy Grid Builder – Deep Dive • Kyle Goodfriend
7
48
IN2HYPERION GROOVY SERIES
• My Adventures in Groovy Calculations - Part 1
• Part 2: Data Validation
• Part 3: Acting On Edited Cells
• Part 4: Run Time Prompts
• Part 5: Accessing Run Time Prompts
• Part 6: Converting a POV into a Fix
• Part 7: Validating Run Time Prompts
• Part 8: Customizing Data Maps and Smart Pushes
• Part 9: Groovy and PBCS is Game Changing in Louisville
• Part 10: Validating Form Data
• Part 11: Accessing Metadata Properties
• Part 12: Learning and Testing Groovy Outside of PBCS
• Part 13: Returning Errors (Data Forms)
• Part 14: Returning Errors (Data Form Cells)
• Part 15: Returning Errors (RTP Edition) add enhancement and
other bug report
• Part 16: Ignore Form Save When No Data Has Been Edited
• Part 17: Force Cell Comments
• Part 18: Real Time Data Movement (Setting The Stage)
• Part 19: Real Time Reporting Webinar with Breakthru Beverage
Group
• Part 20: Groovy On-Premise vs. Groovy Cloud
• Part 21: Real Time Data Movement (Getting Groovy)
• Part 22: Looping Through Member Descendants
• Part 23: Is the POV a level 0 member?
• Part 24: Getting Member Properties?
• Part 25: The DataGridBuilders
• Part 26: Interacting with Smart Lists
• Part 27: Using Maps in Groovy as lookup Tables
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
INSTRUCTIONAL VIDEOS
• Real -Time Reporting in PBCS/ ePBCS
• PBCS Require Comment - Groovy Calculation
• Real Time Reporting Webinar
• Groovy Examples: Webinar Follow-up
I plan to supplement with more BLOG posts that include videos
49ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
50
ORACLE AND GROOVY HOT SPOTS
• PBCS Admin guide overview
Using Groovy Rules.
• Groovy rules
Setting Business Rule Properties.
• The Groovy API Reference on the
E/PBCS library:
• Java API Reference for Oracle Enterprise
Performance Management Cloud Groovy
Rules
• The EPBCS Academy also links to the Groovy
Rules Java API Reference hosted on the library.
• Groovy Business Rule examples
• There are a lot of great books, articles, videos on
Groovy listed here:
http://groovy-lang.org/learn.html
• In particular, I would like to highlight the following
two books:
https://www.manning.com/books/groovy-in-
action-second-edition
https://pragprog.com/book/vslg2/programming-
groovy-2
• The following course on Udemy is very affordable,
and can be a useful asset:
https://www.udemy.com/apache-
groovy/learn/v4/overview
• They can also start by going over the “Language
Specification” section in the following document is
also useful:
http://groovy-lang.org/documentation.html
OTHER SESSIONS
Ask the Experts - Planning Panel
Jun 12th, 2018 02:15 PM - 03:15 PM
Southern Hemisphere II
Top-Down and Bottom-Up Planning at Breakthru Beverage Group
June 13th, 2018 11:45 AM - 12:45 PM
Northern Hemisphere E3
Why Groovy is Game Changing
June 13th, 2018, 3:30 PM - 4:30 PM
Northern Hemisphere E3
Last Minute ODTUG Kscope18 Planning Souvenirs You Will ACTUALLY Use!
June 14th, 9:30 - 11:00 a.m.
Southern Hemisphere II
51ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
THAT’S A WRAP
52Groovy Grid Builder – Deep Dive • Kyle Goodfriend
ODTUG • Kscope 18
8
53
A FEW PARTING GIFTS
• Question & Answer Session
• What would you like to see next at In2Hyperion.com?
» Adventures in Groovy
» Challenge Accepted
Kyle Goodfriend
kyle@in2hyperion.com
614.668.7324
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
THANKS FOR ATTENDING
Kyle Goodfriend
kyle@in2hyperion.com
614.668.7324
ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend 54

More Related Content

What's hot

EPBCS - A New Approach to Planning Implementations
EPBCS - A New Approach to Planning ImplementationsEPBCS - A New Approach to Planning Implementations
EPBCS - A New Approach to Planning ImplementationsJoseph Alaimo Jr
 
Case Study: MySQL migration from latin1 to UTF-8
Case Study: MySQL migration from latin1 to UTF-8Case Study: MySQL migration from latin1 to UTF-8
Case Study: MySQL migration from latin1 to UTF-8Olivier DASINI
 
私はここでつまづいた! Oracle database 11g から 12cへのアップグレードと Oracle Database 12c の新機能@201...
私はここでつまづいた! Oracle database 11g から 12cへのアップグレードと Oracle Database 12c の新機能@201...私はここでつまづいた! Oracle database 11g から 12cへのアップグレードと Oracle Database 12c の新機能@201...
私はここでつまづいた! Oracle database 11g から 12cへのアップグレードと Oracle Database 12c の新機能@201...yoshimotot
 
No more unknown members! Smart data load validation for Hyperion Planning usi...
No more unknown members! Smart data load validation for Hyperion Planning usi...No more unknown members! Smart data load validation for Hyperion Planning usi...
No more unknown members! Smart data load validation for Hyperion Planning usi...Rodrigo Radtke de Souza
 
Workforce Plus: Tips and Tricks to Give Workforce an Extra Kick!
Workforce Plus: Tips and Tricks to Give Workforce an Extra Kick! Workforce Plus: Tips and Tricks to Give Workforce an Extra Kick!
Workforce Plus: Tips and Tricks to Give Workforce an Extra Kick! Alithya
 
I Can do WHAT with PCMCS? Features and Functions, Business Benefits, and Use...
I Can do WHAT with PCMCS?  Features and Functions, Business Benefits, and Use...I Can do WHAT with PCMCS?  Features and Functions, Business Benefits, and Use...
I Can do WHAT with PCMCS? Features and Functions, Business Benefits, and Use...Alithya
 
Google Developer Student Clubs - Brand Guide & Event Kit for Leads (goo.gle_g...
Google Developer Student Clubs - Brand Guide & Event Kit for Leads (goo.gle_g...Google Developer Student Clubs - Brand Guide & Event Kit for Leads (goo.gle_g...
Google Developer Student Clubs - Brand Guide & Event Kit for Leads (goo.gle_g...Pawar Singh
 
Oracle EPM Cloud for Midsize Customers
Oracle EPM Cloud for Midsize CustomersOracle EPM Cloud for Midsize Customers
Oracle EPM Cloud for Midsize CustomersAlithya
 
Fusion ERP Direct Integration with EPBCS
Fusion ERP Direct Integration with EPBCSFusion ERP Direct Integration with EPBCS
Fusion ERP Direct Integration with EPBCSIbraam Sami
 
Case Study: Using EDMCS to Solve Master Data Challenges
Case Study:  Using EDMCS to Solve Master Data ChallengesCase Study:  Using EDMCS to Solve Master Data Challenges
Case Study: Using EDMCS to Solve Master Data ChallengesAlithya
 
The Wright Way into the Cloud: The Argument for ARCS
The Wright Way into the Cloud:  The Argument for ARCSThe Wright Way into the Cloud:  The Argument for ARCS
The Wright Way into the Cloud: The Argument for ARCSAlithya
 
EPRCS: The Reporting Swiss Army Knife
EPRCS:  The Reporting Swiss Army KnifeEPRCS:  The Reporting Swiss Army Knife
EPRCS: The Reporting Swiss Army KnifeAlithya
 
Create bar chart report for p6 r8.3 using bi publisher 11g - Oracle Primavera...
Create bar chart report for p6 r8.3 using bi publisher 11g - Oracle Primavera...Create bar chart report for p6 r8.3 using bi publisher 11g - Oracle Primavera...
Create bar chart report for p6 r8.3 using bi publisher 11g - Oracle Primavera...p6academy
 
Hyperion planning integration with odi
Hyperion planning integration with odiHyperion planning integration with odi
Hyperion planning integration with odiAmit Sharma
 
Understanding HFM System Tables
Understanding HFM System TablesUnderstanding HFM System Tables
Understanding HFM System Tablesaa026593
 
Hyperion Implementation Questionaries
Hyperion Implementation QuestionariesHyperion Implementation Questionaries
Hyperion Implementation QuestionariesAmit Sharma
 
FDMEE Scripting - Cloud and On-Premises - It Ain't Groovy, But It's My Bread ...
FDMEE Scripting - Cloud and On-Premises - It Ain't Groovy, But It's My Bread ...FDMEE Scripting - Cloud and On-Premises - It Ain't Groovy, But It's My Bread ...
FDMEE Scripting - Cloud and On-Premises - It Ain't Groovy, But It's My Bread ...Joseph Alaimo Jr
 
Best Practices for Designing and Building Integrations
Best Practices for Designing and Building IntegrationsBest Practices for Designing and Building Integrations
Best Practices for Designing and Building IntegrationsAlithya
 

What's hot (20)

EPBCS - A New Approach to Planning Implementations
EPBCS - A New Approach to Planning ImplementationsEPBCS - A New Approach to Planning Implementations
EPBCS - A New Approach to Planning Implementations
 
Case Study: MySQL migration from latin1 to UTF-8
Case Study: MySQL migration from latin1 to UTF-8Case Study: MySQL migration from latin1 to UTF-8
Case Study: MySQL migration from latin1 to UTF-8
 
私はここでつまづいた! Oracle database 11g から 12cへのアップグレードと Oracle Database 12c の新機能@201...
私はここでつまづいた! Oracle database 11g から 12cへのアップグレードと Oracle Database 12c の新機能@201...私はここでつまづいた! Oracle database 11g から 12cへのアップグレードと Oracle Database 12c の新機能@201...
私はここでつまづいた! Oracle database 11g から 12cへのアップグレードと Oracle Database 12c の新機能@201...
 
Ppt epm
Ppt epmPpt epm
Ppt epm
 
No more unknown members! Smart data load validation for Hyperion Planning usi...
No more unknown members! Smart data load validation for Hyperion Planning usi...No more unknown members! Smart data load validation for Hyperion Planning usi...
No more unknown members! Smart data load validation for Hyperion Planning usi...
 
Workforce Plus: Tips and Tricks to Give Workforce an Extra Kick!
Workforce Plus: Tips and Tricks to Give Workforce an Extra Kick! Workforce Plus: Tips and Tricks to Give Workforce an Extra Kick!
Workforce Plus: Tips and Tricks to Give Workforce an Extra Kick!
 
I Can do WHAT with PCMCS? Features and Functions, Business Benefits, and Use...
I Can do WHAT with PCMCS?  Features and Functions, Business Benefits, and Use...I Can do WHAT with PCMCS?  Features and Functions, Business Benefits, and Use...
I Can do WHAT with PCMCS? Features and Functions, Business Benefits, and Use...
 
Google Developer Student Clubs - Brand Guide & Event Kit for Leads (goo.gle_g...
Google Developer Student Clubs - Brand Guide & Event Kit for Leads (goo.gle_g...Google Developer Student Clubs - Brand Guide & Event Kit for Leads (goo.gle_g...
Google Developer Student Clubs - Brand Guide & Event Kit for Leads (goo.gle_g...
 
Oracle EPM Cloud for Midsize Customers
Oracle EPM Cloud for Midsize CustomersOracle EPM Cloud for Midsize Customers
Oracle EPM Cloud for Midsize Customers
 
Oracle EPM/BI Overview
Oracle EPM/BI OverviewOracle EPM/BI Overview
Oracle EPM/BI Overview
 
Fusion ERP Direct Integration with EPBCS
Fusion ERP Direct Integration with EPBCSFusion ERP Direct Integration with EPBCS
Fusion ERP Direct Integration with EPBCS
 
Case Study: Using EDMCS to Solve Master Data Challenges
Case Study:  Using EDMCS to Solve Master Data ChallengesCase Study:  Using EDMCS to Solve Master Data Challenges
Case Study: Using EDMCS to Solve Master Data Challenges
 
The Wright Way into the Cloud: The Argument for ARCS
The Wright Way into the Cloud:  The Argument for ARCSThe Wright Way into the Cloud:  The Argument for ARCS
The Wright Way into the Cloud: The Argument for ARCS
 
EPRCS: The Reporting Swiss Army Knife
EPRCS:  The Reporting Swiss Army KnifeEPRCS:  The Reporting Swiss Army Knife
EPRCS: The Reporting Swiss Army Knife
 
Create bar chart report for p6 r8.3 using bi publisher 11g - Oracle Primavera...
Create bar chart report for p6 r8.3 using bi publisher 11g - Oracle Primavera...Create bar chart report for p6 r8.3 using bi publisher 11g - Oracle Primavera...
Create bar chart report for p6 r8.3 using bi publisher 11g - Oracle Primavera...
 
Hyperion planning integration with odi
Hyperion planning integration with odiHyperion planning integration with odi
Hyperion planning integration with odi
 
Understanding HFM System Tables
Understanding HFM System TablesUnderstanding HFM System Tables
Understanding HFM System Tables
 
Hyperion Implementation Questionaries
Hyperion Implementation QuestionariesHyperion Implementation Questionaries
Hyperion Implementation Questionaries
 
FDMEE Scripting - Cloud and On-Premises - It Ain't Groovy, But It's My Bread ...
FDMEE Scripting - Cloud and On-Premises - It Ain't Groovy, But It's My Bread ...FDMEE Scripting - Cloud and On-Premises - It Ain't Groovy, But It's My Bread ...
FDMEE Scripting - Cloud and On-Premises - It Ain't Groovy, But It's My Bread ...
 
Best Practices for Designing and Building Integrations
Best Practices for Designing and Building IntegrationsBest Practices for Designing and Building Integrations
Best Practices for Designing and Building Integrations
 

Similar to Real-Time Planning with Groovy Grid Builder

Where refactoring meets big $$$
Where refactoring meets big $$$Where refactoring meets big $$$
Where refactoring meets big $$$Michał Gruca
 
4Developers 2015: Refactoring za duże pieniądze, pierwsze kroki - Michał Gruca
4Developers 2015: Refactoring za duże pieniądze, pierwsze kroki - Michał Gruca4Developers 2015: Refactoring za duże pieniądze, pierwsze kroki - Michał Gruca
4Developers 2015: Refactoring za duże pieniądze, pierwsze kroki - Michał GrucaPROIDEA
 
Where refactoring meets big money #4developers
Where refactoring meets big money #4developersWhere refactoring meets big money #4developers
Where refactoring meets big money #4developersMichał Gruca
 
OLAP Basics and Fundamentals by Bharat Kalia
OLAP Basics and Fundamentals by Bharat Kalia OLAP Basics and Fundamentals by Bharat Kalia
OLAP Basics and Fundamentals by Bharat Kalia Bharat Kalia
 
MongoDB World 2019: From Traditional Oil and Gas to Sustainable Energy OR Fro...
MongoDB World 2019: From Traditional Oil and Gas to Sustainable Energy OR Fro...MongoDB World 2019: From Traditional Oil and Gas to Sustainable Energy OR Fro...
MongoDB World 2019: From Traditional Oil and Gas to Sustainable Energy OR Fro...MongoDB
 
Big data analytics using a custom SQL engine
Big data analytics using a custom SQL engineBig data analytics using a custom SQL engine
Big data analytics using a custom SQL engineAndrew Tsvelodub
 
SolidWorks Simulation Premium - CAD MicroSolutions
SolidWorks Simulation Premium - CAD MicroSolutionsSolidWorks Simulation Premium - CAD MicroSolutions
SolidWorks Simulation Premium - CAD MicroSolutionsCad MicroSolutions Inc.
 
Meeting the challenges of OLTP Big Data with Scylla
Meeting the challenges of OLTP Big Data with ScyllaMeeting the challenges of OLTP Big Data with Scylla
Meeting the challenges of OLTP Big Data with ScyllaScyllaDB
 
Tugdual Grall - From SQL to NoSQL in less than 40 min - NoSQL matters Paris 2015
Tugdual Grall - From SQL to NoSQL in less than 40 min - NoSQL matters Paris 2015Tugdual Grall - From SQL to NoSQL in less than 40 min - NoSQL matters Paris 2015
Tugdual Grall - From SQL to NoSQL in less than 40 min - NoSQL matters Paris 2015NoSQLmatters
 
Large Scale Vandalism Detection in Knowledge Bases: PyData Berlin 2017
Large Scale Vandalism Detection in Knowledge Bases: PyData Berlin 2017Large Scale Vandalism Detection in Knowledge Bases: PyData Berlin 2017
Large Scale Vandalism Detection in Knowledge Bases: PyData Berlin 2017Alexey Grigorev
 
Bio bigdata
Bio bigdata Bio bigdata
Bio bigdata Mk Kim
 
LesFurets.com: From 0 to Cassandra on AWS in 30 days - Tsunami Alerting Syste...
LesFurets.com: From 0 to Cassandra on AWS in 30 days - Tsunami Alerting Syste...LesFurets.com: From 0 to Cassandra on AWS in 30 days - Tsunami Alerting Syste...
LesFurets.com: From 0 to Cassandra on AWS in 30 days - Tsunami Alerting Syste...DataStax Academy
 
NoSQL and MongoDB Introdction
NoSQL and MongoDB IntrodctionNoSQL and MongoDB Introdction
NoSQL and MongoDB IntrodctionBrian Enochson
 
Google Cloud - Stand Out Features
Google Cloud - Stand Out FeaturesGoogle Cloud - Stand Out Features
Google Cloud - Stand Out FeaturesGDG Cloud Bengaluru
 
qCube: Efficient integration of range query operators over a high dimension d...
qCube: Efficient integration of range query operators over a high dimension d...qCube: Efficient integration of range query operators over a high dimension d...
qCube: Efficient integration of range query operators over a high dimension d...Rodrigo Rocha Silva
 
(Ab)Using GPOs for Active Directory Pwnage
(Ab)Using GPOs for Active Directory Pwnage(Ab)Using GPOs for Active Directory Pwnage
(Ab)Using GPOs for Active Directory PwnagePetros Koutroumpis
 
PostgreSQL 12: What is coming up?, Enterprise Postgres Day
PostgreSQL 12: What is coming up?, Enterprise Postgres DayPostgreSQL 12: What is coming up?, Enterprise Postgres Day
PostgreSQL 12: What is coming up?, Enterprise Postgres DayEDB
 

Similar to Real-Time Planning with Groovy Grid Builder (20)

Where refactoring meets big $$$
Where refactoring meets big $$$Where refactoring meets big $$$
Where refactoring meets big $$$
 
4Developers 2015: Refactoring za duże pieniądze, pierwsze kroki - Michał Gruca
4Developers 2015: Refactoring za duże pieniądze, pierwsze kroki - Michał Gruca4Developers 2015: Refactoring za duże pieniądze, pierwsze kroki - Michał Gruca
4Developers 2015: Refactoring za duże pieniądze, pierwsze kroki - Michał Gruca
 
Where refactoring meets big money #4developers
Where refactoring meets big money #4developersWhere refactoring meets big money #4developers
Where refactoring meets big money #4developers
 
OLAP Basics and Fundamentals by Bharat Kalia
OLAP Basics and Fundamentals by Bharat Kalia OLAP Basics and Fundamentals by Bharat Kalia
OLAP Basics and Fundamentals by Bharat Kalia
 
MongoDB World 2019: From Traditional Oil and Gas to Sustainable Energy OR Fro...
MongoDB World 2019: From Traditional Oil and Gas to Sustainable Energy OR Fro...MongoDB World 2019: From Traditional Oil and Gas to Sustainable Energy OR Fro...
MongoDB World 2019: From Traditional Oil and Gas to Sustainable Energy OR Fro...
 
Big data analytics using a custom SQL engine
Big data analytics using a custom SQL engineBig data analytics using a custom SQL engine
Big data analytics using a custom SQL engine
 
SolidWorks Simulation Premium - CAD MicroSolutions
SolidWorks Simulation Premium - CAD MicroSolutionsSolidWorks Simulation Premium - CAD MicroSolutions
SolidWorks Simulation Premium - CAD MicroSolutions
 
Meeting the challenges of OLTP Big Data with Scylla
Meeting the challenges of OLTP Big Data with ScyllaMeeting the challenges of OLTP Big Data with Scylla
Meeting the challenges of OLTP Big Data with Scylla
 
Tugdual Grall - From SQL to NoSQL in less than 40 min - NoSQL matters Paris 2015
Tugdual Grall - From SQL to NoSQL in less than 40 min - NoSQL matters Paris 2015Tugdual Grall - From SQL to NoSQL in less than 40 min - NoSQL matters Paris 2015
Tugdual Grall - From SQL to NoSQL in less than 40 min - NoSQL matters Paris 2015
 
Large Scale Vandalism Detection in Knowledge Bases: PyData Berlin 2017
Large Scale Vandalism Detection in Knowledge Bases: PyData Berlin 2017Large Scale Vandalism Detection in Knowledge Bases: PyData Berlin 2017
Large Scale Vandalism Detection in Knowledge Bases: PyData Berlin 2017
 
Bio bigdata
Bio bigdata Bio bigdata
Bio bigdata
 
LesFurets.com: From 0 to Cassandra on AWS in 30 days - Tsunami Alerting Syste...
LesFurets.com: From 0 to Cassandra on AWS in 30 days - Tsunami Alerting Syste...LesFurets.com: From 0 to Cassandra on AWS in 30 days - Tsunami Alerting Syste...
LesFurets.com: From 0 to Cassandra on AWS in 30 days - Tsunami Alerting Syste...
 
NoSQL and MongoDB Introdction
NoSQL and MongoDB IntrodctionNoSQL and MongoDB Introdction
NoSQL and MongoDB Introdction
 
Google Cloud - Stand Out Features
Google Cloud - Stand Out FeaturesGoogle Cloud - Stand Out Features
Google Cloud - Stand Out Features
 
FPGA-enhanced Bioinformatics @ NECST
FPGA-enhanced Bioinformatics @ NECSTFPGA-enhanced Bioinformatics @ NECST
FPGA-enhanced Bioinformatics @ NECST
 
qCube: Efficient integration of range query operators over a high dimension d...
qCube: Efficient integration of range query operators over a high dimension d...qCube: Efficient integration of range query operators over a high dimension d...
qCube: Efficient integration of range query operators over a high dimension d...
 
E3MV - Embedded Vision - Sundance
E3MV - Embedded Vision - SundanceE3MV - Embedded Vision - Sundance
E3MV - Embedded Vision - Sundance
 
(Ab)Using GPOs for Active Directory Pwnage
(Ab)Using GPOs for Active Directory Pwnage(Ab)Using GPOs for Active Directory Pwnage
(Ab)Using GPOs for Active Directory Pwnage
 
Gitops Hands On
Gitops Hands OnGitops Hands On
Gitops Hands On
 
PostgreSQL 12: What is coming up?, Enterprise Postgres Day
PostgreSQL 12: What is coming up?, Enterprise Postgres DayPostgreSQL 12: What is coming up?, Enterprise Postgres Day
PostgreSQL 12: What is coming up?, Enterprise Postgres Day
 

More from Kyle Goodfriend

Improve The Planner Experience With Groovy
Improve The Planner Experience With GroovyImprove The Planner Experience With Groovy
Improve The Planner Experience With GroovyKyle Goodfriend
 
Using REST with EPM Cloud Planning
Using REST with EPM Cloud PlanningUsing REST with EPM Cloud Planning
Using REST with EPM Cloud PlanningKyle Goodfriend
 
Things you didn't know you could do with groovy
Things you didn't know you could do with groovyThings you didn't know you could do with groovy
Things you didn't know you could do with groovyKyle Goodfriend
 
Take groovy to places you never thought were possible
Take groovy to places you never thought were possibleTake groovy to places you never thought were possible
Take groovy to places you never thought were possibleKyle Goodfriend
 
Getting Started with Groovy for the Non-Technical Superstars
Getting Started with Groovy for the Non-Technical SuperstarsGetting Started with Groovy for the Non-Technical Superstars
Getting Started with Groovy for the Non-Technical SuperstarsKyle Goodfriend
 
Accelerators at Accelytics
Accelerators at AccelyticsAccelerators at Accelytics
Accelerators at AccelyticsKyle Goodfriend
 
October 2018 ODTUG Webinar - Getting Started with Groovy in EPBCS
October 2018 ODTUG Webinar - Getting Started with Groovy in EPBCSOctober 2018 ODTUG Webinar - Getting Started with Groovy in EPBCS
October 2018 ODTUG Webinar - Getting Started with Groovy in EPBCSKyle Goodfriend
 
ODTUG Getting Groovy with ePBCS
ODTUG Getting Groovy with ePBCSODTUG Getting Groovy with ePBCS
ODTUG Getting Groovy with ePBCSKyle Goodfriend
 
Top-Down and BottomS-Up Planning at Breakthru Beverage Group
Top-Down and BottomS-Up Planning at Breakthru Beverage GroupTop-Down and BottomS-Up Planning at Breakthru Beverage Group
Top-Down and BottomS-Up Planning at Breakthru Beverage GroupKyle Goodfriend
 
CHCC 2017 Q1 Event Overview
CHCC 2017 Q1 Event OverviewCHCC 2017 Q1 Event Overview
CHCC 2017 Q1 Event OverviewKyle Goodfriend
 
Top Down and Bottom Up Planning at Breakthru Beverage Group Follow Up
Top Down and Bottom Up Planning at Breakthru Beverage Group Follow UpTop Down and Bottom Up Planning at Breakthru Beverage Group Follow Up
Top Down and Bottom Up Planning at Breakthru Beverage Group Follow UpKyle Goodfriend
 
Top Down and Bottom Up Planning at Breakthru Beverage Group
Top Down and Bottom Up Planning at Breakthru Beverage GroupTop Down and Bottom Up Planning at Breakthru Beverage Group
Top Down and Bottom Up Planning at Breakthru Beverage GroupKyle Goodfriend
 
Ohio Valley Oracle Application User Group
Ohio Valley Oracle Application User GroupOhio Valley Oracle Application User Group
Ohio Valley Oracle Application User GroupKyle Goodfriend
 
Create Unlimited Custom Spreads for Driver Based Planning
Create Unlimited Custom Spreads for Driver Based PlanningCreate Unlimited Custom Spreads for Driver Based Planning
Create Unlimited Custom Spreads for Driver Based PlanningKyle Goodfriend
 
Automating Hyperion Planning Tasks
Automating Hyperion Planning TasksAutomating Hyperion Planning Tasks
Automating Hyperion Planning TasksKyle Goodfriend
 
Driving Accountability Through Disciplined Planning at Abercrombie & Fitch
Driving Accountability Through Disciplined Planning at Abercrombie & FitchDriving Accountability Through Disciplined Planning at Abercrombie & Fitch
Driving Accountability Through Disciplined Planning at Abercrombie & FitchKyle Goodfriend
 
Supercharge PBCS with PowerShell
Supercharge PBCS with PowerShellSupercharge PBCS with PowerShell
Supercharge PBCS with PowerShellKyle Goodfriend
 

More from Kyle Goodfriend (18)

Improve The Planner Experience With Groovy
Improve The Planner Experience With GroovyImprove The Planner Experience With Groovy
Improve The Planner Experience With Groovy
 
Using REST with EPM Cloud Planning
Using REST with EPM Cloud PlanningUsing REST with EPM Cloud Planning
Using REST with EPM Cloud Planning
 
Things you didn't know you could do with groovy
Things you didn't know you could do with groovyThings you didn't know you could do with groovy
Things you didn't know you could do with groovy
 
Take groovy to places you never thought were possible
Take groovy to places you never thought were possibleTake groovy to places you never thought were possible
Take groovy to places you never thought were possible
 
Getting Started with Groovy for the Non-Technical Superstars
Getting Started with Groovy for the Non-Technical SuperstarsGetting Started with Groovy for the Non-Technical Superstars
Getting Started with Groovy for the Non-Technical Superstars
 
Accelerators at Accelytics
Accelerators at AccelyticsAccelerators at Accelytics
Accelerators at Accelytics
 
18.11 texas user group
18.11 texas user group18.11 texas user group
18.11 texas user group
 
October 2018 ODTUG Webinar - Getting Started with Groovy in EPBCS
October 2018 ODTUG Webinar - Getting Started with Groovy in EPBCSOctober 2018 ODTUG Webinar - Getting Started with Groovy in EPBCS
October 2018 ODTUG Webinar - Getting Started with Groovy in EPBCS
 
ODTUG Getting Groovy with ePBCS
ODTUG Getting Groovy with ePBCSODTUG Getting Groovy with ePBCS
ODTUG Getting Groovy with ePBCS
 
Top-Down and BottomS-Up Planning at Breakthru Beverage Group
Top-Down and BottomS-Up Planning at Breakthru Beverage GroupTop-Down and BottomS-Up Planning at Breakthru Beverage Group
Top-Down and BottomS-Up Planning at Breakthru Beverage Group
 
CHCC 2017 Q1 Event Overview
CHCC 2017 Q1 Event OverviewCHCC 2017 Q1 Event Overview
CHCC 2017 Q1 Event Overview
 
Top Down and Bottom Up Planning at Breakthru Beverage Group Follow Up
Top Down and Bottom Up Planning at Breakthru Beverage Group Follow UpTop Down and Bottom Up Planning at Breakthru Beverage Group Follow Up
Top Down and Bottom Up Planning at Breakthru Beverage Group Follow Up
 
Top Down and Bottom Up Planning at Breakthru Beverage Group
Top Down and Bottom Up Planning at Breakthru Beverage GroupTop Down and Bottom Up Planning at Breakthru Beverage Group
Top Down and Bottom Up Planning at Breakthru Beverage Group
 
Ohio Valley Oracle Application User Group
Ohio Valley Oracle Application User GroupOhio Valley Oracle Application User Group
Ohio Valley Oracle Application User Group
 
Create Unlimited Custom Spreads for Driver Based Planning
Create Unlimited Custom Spreads for Driver Based PlanningCreate Unlimited Custom Spreads for Driver Based Planning
Create Unlimited Custom Spreads for Driver Based Planning
 
Automating Hyperion Planning Tasks
Automating Hyperion Planning TasksAutomating Hyperion Planning Tasks
Automating Hyperion Planning Tasks
 
Driving Accountability Through Disciplined Planning at Abercrombie & Fitch
Driving Accountability Through Disciplined Planning at Abercrombie & FitchDriving Accountability Through Disciplined Planning at Abercrombie & Fitch
Driving Accountability Through Disciplined Planning at Abercrombie & Fitch
 
Supercharge PBCS with PowerShell
Supercharge PBCS with PowerShellSupercharge PBCS with PowerShell
Supercharge PBCS with PowerShell
 

Recently uploaded

FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsPrecisely
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 

Recently uploaded (20)

The transition to renewables in India.pdf
The transition to renewables in India.pdfThe transition to renewables in India.pdf
The transition to renewables in India.pdf
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power Systems
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 

Real-Time Planning with Groovy Grid Builder

  • 1. Groovy Grid Builder – Deep Dive • Kyle Goodfriend LAST MINUTE ODTUG KSCOPE18 PLANNING SOUVENIRS June 14th , 9:30 - 11:00 a.m. Southern Hemisphere II, Fifth Level Kyle Goodfriend ODTUG • Kscope 18
  • 2. 2 GROOVY GRIDBUILDER DEEP DIVE AGENDA INTRODUCTION PBCS AND GROOVY THE GRIDBUILDER GRIDBUILDER METHODS REAL WORLD EXAMPLES PRODUCTIVITY GUIDANCE AND SUGGESTIONS WHERE TO GO NEXT WRAP-UP ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 3. INTRODUCTION 3Groovy Grid Builder – Deep Dive • Kyle Goodfriend ODTUG • Kscope 18 1
  • 4. Slide 4 HOUSEKEEPING • Questions and Answers » We will answer questions throughout the presentation » Bring questions with your name/email/phone number up to the front at the end of the presentation and I will make sure they get answered ODTUG • KScope18 Top-Down & Bottom-Up Planning at Breakthru Beverage Group Wed, Jun 13, 2018 (11:45 PM - 12:45 PM)
  • 5. 5 WHO AM I? • BBA, concentration in Finance • Moved into technology because I was always trying to find a way to eliminate redundant tasks (AKA – hated my job) • Started using Essbase to consolidate multiple GLs with consolidated companies • Started consulting in 1999 • Really enjoy what I do because it is artistic and creative - finding solutions for complex problems ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend kyle@in2hyperion.com 614.668.7324
  • 6. 6 WHY DID I START USING GROOVY CALCULATIONS? • Forms were taking minutes to update » Hundreds of products » Data was entered at parent level » Hundreds of allocations were executed • Client wanted real time reporting » Users wanted full P&L consolidated reporting when product/material group/delivery channel were made » Users wanted full P&L consolidated reporting when employee level changes were made • Complex data validation was required in data that was changed » Monthly spreading has to have a net impact of zero » Employee level validation was required ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 7. PERFORMANCE AND USABILITY 7 99%IMPROVEMENT 98% 99% Reporting includes all updates from detailed modules (product, Capex, workforce, and similar modules) and is included in real time as changes are made Consolidated Reporting Reporting includes all updates from detailed modules (product, Capex, workforce, and similar modules) at scheduled intervals users have to wait to see consolidated information Groovy eliminates the need to consolidate the BSO cube and copies data directly from the ASO cube at a consolidated level .2 Seconds Dimensions are consolidated and copied to the P&L model 82.9 Seconds Consolidated P&L Product detailed dimensions are consolidated and moved to the P&L model Groovy selects only the cells that where edited and copies only what changed to the reporting model 1.0 Seconds All data on the form is synchronized 14.5 Seconds Smart Push Data synchronizes to the reporting cube for analysis 01 0110 0001 01101 Groovy selects only edited cells and executes the logic on only products and periods that changed 0.3 Seconds All products on the form are calculated 26.1 Seconds Business Logic Growth rates are entered at total product breakouts and allocated to the detailed level With the inclusion of Groovy and access to the Java API, more customization can be integrated to maximum performance and achieve real time consolidated reporting Submit Planner Input User submits updates to the Gross Profit model at a detailed product level that exists at a more granular level than in the P&L model ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 8. ADMINISTRATIVE FLEXIBILITY 8 Reporting includes all updates from detailed modules (product, Capex, workforce, and similar modules) and is included in real time as changes are made Consolidated Reporting Reporting includes all updates from detailed modules (product, Capex, workforce, and similar modules) at scheduled intervals users have to wait to see consolidated information Automated Process Administrative processes are executed to run all business logic and model synchronizations The entire data set is consolidated and moved to the P&L model 12.0 Seconds Dimensions are consolidated and copied to the P&L model 663.6 Seconds Global Consolidation Global product consolidations are often required to catch all changes and completed during maintenance windows 99% 99% ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 9. NEVER THOUGHT I WOULD SAY THIS It is possible to build a planning application without writing a single BSO calculation ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend 9
  • 10. PBCS AND GROOVY Groovy is now available in ePBCS as calculation 10Groovy Grid Builder – Deep Dive • Kyle Goodfriend ODTUG • Kscope 18 2
  • 11. 11 CONVERTING TO GROOVY CALCULATION • Open Rules in PBCS and create a new rule • Change the dropdown box with from Designer to Edit Script • Change the Script type dropdown box to Groovy Script ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 12. 12 WHAT IS AVAILABLE WITH GROOVY CALCULATIONS • Iterating through data grid cells » Color coding » Data validation » Identification of edited and non-edited cells • Data synchronization between ASO/BSO and BSO/ASO • Execute business logic • Mapping data between cubes • Can be executed in stages » Pre-save » On-load » Post-save Groovy Grid Builder – Deep Dive • Kyle GoodfriendODTUG • Kscope 18
  • 13. THE GRID BUILDER The GridBuilder methods provide a completely customized way to do so many things. Your creativity is the only thing that limits the possibilities. It is the gateway to completing the circle of doing everything in Groovy ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend 13 3
  • 14. Groovy Grid Builder – Deep Dive • Kyle Goodfriend 14 GRIDBUILDER CONCEPTS • Each grid has » A POV » Column headers » Row headers • Grids can » Build = refresh » Save = submit • Grids have limits » 500,000 cell limit when reading » 200,000 cell limit when saving ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 15. Groovy Grid Builder – Deep Dive • Kyle GoodfriendODTUG • Kscope 18 15 GRIDBUILDER USE CASES • Benefits » Move Data from ASO to BSO to eliminate the need for consolidations » Calculate outside of Essbase » If the DataMap is used it bypases user security • Creative use cases » Mapping data when moving from cube to cube » Clearing ASO without limits – Data Maps only clear what is in the BSO cube, not everything in the POV » Get POV with data (aka, suppression) Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 16. GRIDBUILDER METHODS Before you can become productive, get to know the methods. 16Groovy Grid Builder – Deep Dive • Kyle Goodfriend ODTUG • Kscope 18 4
  • 17. Groovy Grid Builder – Deep Dive • Kyle Goodfriend 17 GRID BUILDER CLASS OVERVIEW • Classes » DataGridBuilder (submit data) » DataGridDefinitionBuilder (read data) • DataGridBuilder » Create a grid » Specify data » Save the data • DataGridDefinitionBuilder » Create a grid » Retrieve the data » Can use functions ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 18. Groovy Grid Builder – Deep Dive • Kyle Goodfriend 18 GRIDBUILDER METHODS • DataGridBuilder » addColumn » addPov » addRow » build » saveGrid (submit) • DataGridDefinitionBuilder » addColumn » addPov » addRow » setSuppressMissingBlocks » Build (refresh) ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 19. 19 DATAGRIDBUILDER EXAMPLE // Setup the connection to the plan type Cube cube = operation.application.getCube("Plan1") DataGridBuilder builder = cube.getDataGridBuilder("MM/DD/YYYY") // Setup the grid POV, Rows, and Columns builder.addPov('Salary', 'Current', 'Local', 'BU Version_1’) builder.addColumn('FY16', 'FY16', 'FY16’) builder.addColumn('Jan', 'Feb', 'Mar’) // Add rows to the grid builder.addRow(['Department 1', 'Employee 1'], [30000, 30000, 30000]) builder.addRow(['Department 5', 'Employee 2'], [40000, 40000, 40000]) builder.addRow(['Department 1', 'Employee 3'], [30000, 30000, 30000]) // Create a status class to hold the results DataGridBuilder.Status status = new DataGridBuilder.Status() // Build the grid – basically a refresh/retrieve DataGrid grid = builder.build(status) println("Total number of cells accepted: status.numAcceptedCells") println("Total number of cells rejected: status.numRejectedCells") println("First 100 rejected cells: status.cellsRejected") // Save the data to the cube cube.saveGrid(grid) ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 20. 20 DATAGRIDDEFINITIONBUILDER EXAMPLE // Setup the connection to the plan type Cube cube = operation.application.getCube("Plan1") //Create the grid definition builder DataGridDefinitionBuilder builder = cube.dataGridDefinitionBuilder // Add the POV – Dimensions and a collection of the members in those dimensions builder.addPov(['Years', 'Scenario', 'Currency', 'Period', 'Version', 'Entity’], [['FY16'], ['Current'], ['Local'], ['BegBalance'], ['BU Version_1'], ['No Entity’]]) // Add the columns – 2 parameters, collection of dimensions and // collection of collections of members in those dimensions builder.addColumn(['Years', 'Account’], [['Children(Years)'],['Min Salary','Max Salary','Min Bonus','Max Bonus']]) // Add rows no data - in this class as it is retrieving data builder.addRow(['Grades'], [ ['ILvl0Descendants("Grades")']]) // Build the grid DataGridDefinition gridDefinition = builder.build() // Load a data grid from the specified grid definition and cube DataGrid dataGrid = cube.loadGrid(gridDefinition, false) ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 21. REAL WORLD EXAMPLES A walk through gridbuilder use cases ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend 21 5
  • 22. 22 DEMONSTRATION CLEAR ASO DATA • DataMaps won’t work when removing data in the BSO application first » Removing TBHs » Removing new products • Clearing data when the Smart Push clear limits are reached ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 23. 23 SCRIPT SETUP /*RTPS: {RTP_YesNoClearBlk} {RTP_Vendor}*/ def mbUs = messageBundle(["validation.AbortClear":"You have chosen to NOT clear the selected Brand Family. No Action has been taken. To proceed with clearing, please acknowledge by selecting (YES) from the drop down menu. Otherwise please click (Cancel). "]) def mbl = messageBundleLoader(["en" : mbUs]) //If yes, proceed to second rule in rule set if(rtps.RTP_YesNoClearBlk.getEssbaseValue() != "1") { println rtps.RTP_YesNoClearBlk.getEssbaseValue() println "The user cancelled the operation" throwVetoException(mbl, "validation.AbortClear", rtps.RTP_YesNoClearBlk) } //set account map def acctMap = ['Regular_Cases':'Regular_Cases', 'Net_Sales':'42001', 'Cost_of_Sales_without_Samples':'50001', 'Gallonage_Tax':'50015', 'Depletion_Allowance_Manual_Chargeback':'56010', 'Gain_Loss_Inv_Reval':'50010', 'Supplier_Commitments':'56055', 'Supplier_Spend_Non_Committed':'56300', 'Samples':'56092' ] ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 24. 24 GETTING THE POV // Get POV String sCompany = operation.grid.getCellWithMembers().getMemberName("Company") String sMaterialGroup = operation.grid.getCellWithMembers().getMemberName("Material_Group") String sChannel = operation.grid.getCellWithMembers().getMemberName("Channel") String sVendor = rtps.RTP_Vendor.getMember() //operation.grid.getCellWithMembers().getMemberName("Vendor") String sSource = operation.grid.getCellWithMembers().getMemberName("Source") String sVersion = operation.grid.getCellWithMembers().getMemberName("Version") String sScenario = operation.grid.getCellWithMembers().getMemberName("Scenario") String sYear = operation.grid.getCellWithMembers().getMemberName("Years") ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 25. 25 USING THE GRIDBUILDER TO CLEAR THE DATA //Fin Grid Setup Cube rGPCube = operation.application.getCube("rGP") DataGridBuilder rGPGrid = rGPCube.dataGridBuilder("MM/DD/YYYY") rGPGrid.addPov(sYear,sScenario,'OEP_Working',sCompany, sMaterialGroup,sChannel,sVendor,sSource,'MTD’) // Clear the accounts in the account map rGPGrid.addColumn('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug’, 'Sep','Oct','Nov','Dec’) acctMap.eachWithIndex { AcctItem , i -> rGPGrid.addRow([AcctItem.key,'Local'],[0,0,0,0,0,0,0,0,0,0,0,0]) rGPGrid.addRow([AcctItem.key,'USD'],[0,0,0,0,0,0,0,0,0,0,0,0]) } // Clear additional input accounts def OtherAccounts = ['GP_Level 1','GP_Level 2','Avg Price/ Case Inp','GP Level 1 & Inp','GP Level 2 % Inp'].each{ rGPGrid.addRow([it,'local'],[0,0,0,0,0,0,0,0,0,0,0,0]) rGPGrid.addRow([it,'USD'],[0,0,0,0,0,0,0,0,0,0,0,0]) } DataGridBuilder.Status rstatus = new DataGridBuilder.Status() DataGrid rgrid = rGPGrid.build(rstatus) println("Total number of cells accepted: $rstatus.numAcceptedCells") println("Total number of cells rejected: $rstatus.numRejectedCells") println("First 100 rejected cells: $rstatus.cellsRejected") rGPCube.saveGrid(rgrid) ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 26. 26 DEMONSTRATION REAL-TIME REPORTING • Move data to ASO without consolidations • Map data between different accounts ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 27. 27 PERFORMANCE AND PROCESS ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend 99%IMPROVEMENT 98% 99% Reporting includes all updates from detailed modules (product, Capex, workforce, and similar modules) and is included in real time as changes are made Consolidated Reporting Reporting includes all updates from detailed modules (product, Capex, workforce, and similar modules) at scheduled intervals users have to wait to see consolidated information Groovy eliminates the need to consolidate the BSO cube and copies data directly from the ASO cube at a consolidated level .2 Seconds Dimensions are consolidated and copied to the P&L model 82.9 Seconds Consolidated P&L Product detailed dimensions are consolidated and moved to the P&L model Groovy selects only the cells that where edited and copies only what changed to the reporting model 1.0 Seconds All data on the form is synchronized 14.5 Seconds Smart Push Data synchronizes to the reporting cube for analysis 01 0110 0001 01101 Groovy selects only edited cells and executes the logic on only products and periods that changed 0.3 Seconds All products on the form are calculated 26.1 Seconds Business Logic Growth rates are entered at total product breakouts and allocated to the detailed level With the inclusion of Groovy and access to the Java API, more customization can be integrated to maximum performance and achieve real time consolidated reporting Submit Planner Input User submits updates to the Gross Profit model at a detailed product level that exists at a more granular level than in the P&L model
  • 28. 28 TYPICAL CONSOLIDATION VS GRIDBUILDER ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend Detailed App Consolidated P&L Detailed App Consolidated P&L NON GROOVY • All dimensions need to be consolidated • Movement from ASO is not possible • Movement is batched and scheduled WITH GROOVY • NO BSO consolidation is required • Data can be transferred from ASO • Movement is executed on form save
  • 29. 29 SETTING UP THE VARIABLES AND PUSHING DATA def startTime = currentTimeMillis() def procTime = currentTimeMillis() def elapsed=(currentTimeMillis()-startTime)/1000 Calendar calendar = Calendar.getInstance() calendar.setTimeInMillis(currentTimeMillis()) def now = calendar.getTime() def dtstmp = now.format("MM/dd/yyyy") elapsed=(currentTimeMillis()-procTime)/1000 procTime = currentTimeMillis() println "****************************************************" println "Time taken for allocation and consolidation = $elapsed secs" println "Total Time = " + (currentTimeMillis()-startTime)/1000 + " secs" println "****************************************************" //**************************************************************************** // Data Movement between Apps //**************************************************************************** // Get POV String sCompany = operation.grid.getCellWithMembers().getMemberName("Company") def sMaterialGroup = operation.grid.getCellWithMembers().getMemberName("Material_Group") String sChannel = operation.grid.getCellWithMembers().getMemberName("Channel") // Get a list of edited rows def lstVendors = [] operation.grid.dataCellIterator({DataCell cell -> cell.edited}).each{ lstVendors.add(it.getMemberName("Vendor")) } String strVendors = """"${lstVendors.unique().join('","')}"""" println "data push running for " + strVendors if(operation.grid.hasSmartPush("GP_SmartPush") && lstVendors) operation.grid.getSmartPush("GP_SmartPush").execute(["Vendor":strVendors,"Currency":'"Local","USD”’]) elapsed=(currentTimeMillis()-procTime)/1000 procTime = currentTimeMillis() println "****************************************************" println "Time taken for data push = $elapsed secs" println "Total Time = " + (currentTimeMillis()-startTime)/1000 + " secs" println "****************************************************" ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 30. 30 CREATING THE READER GRID //set account map def acctMap = ['Regular_Cases':'Regular_Cases', 'Net_Sales':'42001', 'Cost_of_Sales_without_Samples':'50001', 'Gallonage_Tax':'50015', 'Depletion_Allowance_Manual_Chargeback':'56010', 'Gain_Loss_Inv_Reval':'50010', 'Supplier_Commitments':'56055', 'Supplier_Spend_Non_Committed':'56300', 'Samples':'56092', 'GP_NDF':'56230', 'GP_BDF':'56200', 'GP_Contract_Amortization':'56205', 'Sample_Adjustment':'56090' ] Cube lookupCube = operation.application.getCube("rGP") DataGridDefinitionBuilder builder = lookupCube.dataGridDefinitionBuilder() builder.addPov(['Years', 'Scenario', 'Version', 'Company','Channel','Material_Group','Source','Vendor','View'], [['&v_PlanYear'], ['OEP_Plan’], ['OEP_Working'], [sCompany],['Tot_Channel'],['Total_Material_Group'],['Tot_Source'],['Tot_Vendor'],['MTD']]) builder.addColumn(['Period','Currency'], [ ['ILvl0Descendants("YearTotal")'],['Local','USD'] ]) for ( e in acctMap ) { builder.addRow(['Account'], [ [e.key] ]) } DataGridDefinition gridDefinition = builder.build() // Load the data grid from the lookup cube DataGrid dataGrid = lookupCube.loadGrid(gridDefinition, false) def povmbrs = dataGrid.pov println "POV:" println povmbrs*.essbaseMbrName def rowmbrs = dataGrid.rows println"ROWS HEADER:" println rowmbrs.headers*.essbaseMbrName def colmbrs = dataGrid.columns println"COLUMNS:" println colmbrs[0]*.essbaseMbrName println colmbrs[1]*.essbaseMbrName def tmpColMbrs = [] //colmbrs[0].each{println it.essbaseMbrName} ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 31. 31 CREATING THE SUBMISSION FORMS //Fin Grid Setup Cube finCube = operation.application.getCube("Fin") Cube rfinCube = operation.application.getCube("rFin") DataGridBuilder finGrid = finCube.dataGridBuilder("MM/DD/YYYY") DataGridBuilder rfinGrid = rfinCube.dataGridBuilder("MM/DD/YYYY") finGrid.addPov('&v_PlanYear','OEP_Plan','OEP_Working',sCompany,'No_Center','GP_Model') rfinGrid.addPov('&v_PlanYear','OEP_Plan','OEP_Working',sCompany,'No_Center','GP_Model','MTD') def colnames = colmbrs[0]*.essbaseMbrName def colnames1 = colmbrs[1]*.essbaseMbrName String scolmbrs = "'" + colnames.join("', '") + "'" finGrid.addColumn(colmbrs[0]*.essbaseMbrName as String[]) rfinGrid.addColumn(colmbrs[0]*.essbaseMbrName as String[]) finGrid.addColumn(colmbrs[1]*.essbaseMbrName as String[]) rfinGrid.addColumn(colmbrs[1]*.essbaseMbrName as String[]) def lstCurrency = ["Local","USD"] def UniqueMonths = colnames.unique() def iCurrencyCount = 0 dataGrid.dataCellIterator('Jan','Local').each{ it -> def sAcct = "${acctMap.get(it.getMemberName('Account'))}" def sValues = [] List addcells = new ArrayList() UniqueMonths.each{cMonth -> lstCurrency.each{cCurrency -> sValues.add(it.crossDimCell(cMonth.toString(),cCurrency.toString()).data) addcells << it.crossDimCell(cMonth.toString(),cCurrency.toString()).data //println cMonth.essbaseMbrName + cCurrency.toString() } } finGrid.addRow([acctMap.get(it.getMemberName('Account'))],addcells) rfinGrid.addRow([acctMap.get(it.getMemberName('Account'))],addcells) println "${acctMap.get(it.getMemberName('Account'))}" + "," + sValues.join(",") } ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 32. 32 EXECUTING THE SUBMISSION FORMS DataGridBuilder.Status status = new DataGridBuilder.Status() DataGridBuilder.Status rstatus = new DataGridBuilder.Status() DataGrid grid = finGrid.build(status) DataGrid rgrid = rfinGrid.build(rstatus) println("Total number of cells accepted: $status.numAcceptedCells") println("Total number of cells rejected: $status.numRejectedCells") println("First 100 rejected cells: $status.cellsRejected") finCube.saveGrid(grid) println("Total number of cells accepted: $rstatus.numAcceptedCells") println("Total number of cells rejected: $rstatus.numRejectedCells") println("First 100 rejected cells: $rstatus.cellsRejected") rfinCube.saveGrid(rgrid) elapsed=(currentTimeMillis()-procTime)/1000 procTime = currentTimeMillis() println "****************************************************" println "Time taken copy to fin = $elapsed secs" println "Total Time = " + (currentTimeMillis()-startTime)/1000 + " secs" println "****************************************************" ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 33. 33 DEMONSTRATION CALCULATING OUTSIDE OF THE ESSBASE ENGINE • Calculating Currency in ASO • Connecting forms with business logic directly to an ASO play type » Rewrite form rate*volume or currency conversion » NBF calculate accounts ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 34. SETTING UP THE POV // define common functions def checkZero(double dVal=0) { if(dVal == 0) { return 1 } else { return dVal } } boolean convertCurrency(def account='') { Dimension AccountDim = operation.application.getDimension("Account") Member AccountMbr = AccountDim.getMember(account) def memberProps = AccountMbr.toMap() if(memberProps['UDA'].toString().contains('IgnoreCurrencyConversion')) return false else return true } //set account map %Script(name:="GP - Account Map",application:="BreakFin",plantype:="GP") // POV String sCompany = operation.grid.getCellWithMembers().getMemberName("Company") String sVersion = operation.grid.getCellWithMembers().getMemberName("Version") String sScenario = operation.grid.getCellWithMembers().getMemberName("Scenario") String sYear = operation.grid.getCellWithMembers().getMemberName("Years") String sMaterialGroup = operation.grid.getCellWithMembers().getMemberName("Material_Group") String sChannel = operation.grid.getCellWithMembers().getMemberName("Channel") String sSource = operation.grid.getCellWithMembers().getMemberName("Source") def currencyRates = [:] ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend def acctMap = ['Regular_Cases':'Regular_Cases', 'Net_Sales':'42001', 'Cost_of_Sales_without_Samples':'50001', 'Gallonage_Tax':'50015', 'Depletion_Allowance_Manual_Chargeback':'56010', 'Gain_Loss_Inv_Reval':'50010', 'Supplier_Commitments':'56055', 'Supplier_Spend_Non_Committed':'56300', 'Samples':'56092' ]
  • 35. 35 CREATE THE CURRENCY RATES MAP // Build currency for the company Cube lookupCube = operation.application.getCube("GP") DataGridDefinitionBuilder builder = lookupCube.dataGridDefinitionBuilder() builder.addPov(['Years', 'Scenario', 'Version','Channel','Material_Group','Source','Vendor’, 'Currency','Account’], [[sYear],[sScenario],[sVersion],['No_Channel'],['No_Material_Group’], ['Input'],['No_Vendor_Assigned'],['Local'],['End_C_Rate']]) builder.addColumn(['Period'], [ ['ILvl0Descendants("YearTotal")']]) builder.addRow(['Company'], [ [sCompany] ]) DataGridDefinition gridDefinition = builder.build() // Load the data grid from the lookup cube lookupCube.loadGrid(gridDefinition, false).withCloseable { dataGrid -> dataGrid.dataCellIterator().each{ rate -> currencyRates.put(rate.getMemberName('Period'),checkZero(rate.data)) } } ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 36. 36 SETUP THE WRITEBACK GRID BUILDERS // Setup Grid to submit results // Get list of vendors def listVendors = operation.grid.rows.headers*.essbaseMbrName.collect {vendor, account -> return vendor}.unique() // List of calculated members def listAccounts = ["Regular_Cases","Net_Sales","GP_Level_1","Cost_of_Sales_without_Samples", "GP_Level_2","Depletion_Allowance_Manual_Chargeback"] //Fin Grid Setup Cube finCube = operation.application.getCube("GP") Cube rfinCube = operation.application.getCube("rGP") DataGridBuilder bsoGrid = finCube.dataGridBuilder("MM/DD/YYYY") DataGridBuilder aspGrid = rfinCube.dataGridBuilder("MM/DD/YYYY") bsoGrid.addPov(sYear,sScenario,sVersion,sChannel,sMaterialGroup,sSource,sCompany) aspGrid.addPov(sYear,sScenario,sVersion,sChannel,sMaterialGroup,sSource,sCompany,'MTD') bsoGrid.addColumn('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec') aspGrid.addColumn('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec') def lstCurrency = ["Local","USD"] ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 37. 37 ADD THE ROWS AND VALUES TO SUBMIT (PART 1) // loop through the grid on the form listVendors.each{ vendor -> listAccounts.each{ account -> def sValues = [] def sValuesUSD = [] List addcells = new ArrayList() List addcellsUSD = new ArrayList() ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'].each{cMonth -> ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 38. 38 ADD THE ROWS AND VALUES TO SUBMIT (PART 2) double setValue switch (account) { case "Net_Sales": setValue = operation.grid.getCellWithMembers("Avg_Price/Case_Inp",cMonth.toString(),vendor.toString()).data * operation.grid.getCellWithMembers("Regular_Cases",cMonth.toString(),vendor.toString()).data break case "GP_Level_1": double netSales = operation.grid.getCellWithMembers("Avg_Price/Case_Inp",cMonth.toString(),vendor.toString()).data * operation.grid.getCellWithMembers("Regular_Cases",cMonth.toString(),vendor.toString()).data setValue = netSales * operation.grid.getCellWithMembers("GP_1_%_Inp",cMonth.toString(),vendor.toString()).data break case "Cost_of_Sales_without_Samples": double netSales = operation.grid.getCellWithMembers("Avg_Price/Case_Inp",cMonth.toString(),vendor.toString()).data * operation.grid.getCellWithMembers("Regular_Cases",cMonth.toString(),vendor.toString()).data double gp1 = netSales * operation.grid.getCellWithMembers("GP_1_%_Inp",cMonth.toString(),vendor.toString()).data setValue = netSales - gp1 break case "GP_Level_2": double netSales = operation.grid.getCellWithMembers("Avg_Price/Case_Inp",cMonth.toString(),vendor.toString()).data * operation.grid.getCellWithMembers("Regular_Cases",cMonth.toString(),vendor.toString()).data setValue = netSales * operation.grid.getCellWithMembers("GP_2_%_Inp",cMonth.toString(),vendor.toString()).data break case "Depletion_Allowance_Manual_Chargeback": double netSales = operation.grid.getCellWithMembers("Avg_Price/Case_Inp",cMonth.toString(),vendor.toString()).data * operation.grid.getCellWithMembers("Regular_Cases",cMonth.toString(),vendor.toString()).data double gp1 = netSales * operation.grid.getCellWithMembers("GP_1_%_Inp",cMonth.toString(),vendor.toString()).data double gp2 = netSales * operation.grid.getCellWithMembers("GP_2_%_Inp",cMonth.toString(),vendor.toString()).data setValue = netSales - gp1 break default: setValue = operation.grid.getCellWithMembers(account.toString(),cMonth.toString(),vendor.toString()).data break } ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 39. 39 ADD THE ROWS AND VALUES TO SUBMIT (PART 3) sValues.add(setValue) addcells << setValue // Convert Currency if account should be converted if(convertCurrency(account)){ sValuesUSD.add(currencyRates[cMonth].toString().toDouble() * setValue) addcellsUSD << currencyRates[cMonth].toString().toDouble() * setValue } else { sValuesUSD.add(setValue) addcellsUSD << setValue } } bsoGrid.addRow([account.toString(),vendor.toString(),'Local'],addcells) bsoGrid.addRow([account.toString(),vendor.toString(),'USD'],addcellsUSD) aspGrid.addRow([account.toString(),vendor.toString(),'Local'],addcells) aspGrid.addRow([account.toString(),vendor.toString(),'USD'],addcellsUSD) println account + ' ' + vendor + ' Local:' + addcells println account + ' ' + vendor + ' USD:' + addcellsUSD } } ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 40. 40 SUBMIT AND GET THE STATUS OF THE GRID BUILDER DataGridBuilder.Status status = new DataGridBuilder.Status() DataGridBuilder.Status rstatus = new DataGridBuilder.Status() DataGrid grid = bsoGrid.build(status) DataGrid rgrid = aspGrid.build(rstatus) println("Total number of cells accepted: $status.numAcceptedCells") println("Total number of cells rejected: $status.numRejectedCells") println("First 100 rejected cells: $status.cellsRejected") finCube.saveGrid(grid) println("Total number of cells accepted: $rstatus.numAcceptedCells") println("Total number of cells rejected: $rstatus.numRejectedCells") println("First 100 rejected cells: $rstatus.cellsRejected") rfinCube.saveGrid(rgrid) ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 41. 41 CHECK OUT THE RETURN LOG CREATED Log messages : *** data validation for the grid Regular_Cases NBF1 Local:[3.0, 2.0, 2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Regular_Cases NBF1 USD:[3.0, 2.0, 2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Net_Sales NBF1 Local:[39.0, 126.0, 44.0, 4.0, 10.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Net_Sales NBF1 USD:[39.0, 12.600000000000001, 8.8, 1.2000000000000002, 4.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] GP_Level_1 NBF1 Local:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] GP_Level_1 NBF1 USD:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Cost_of_Sales_without_Samples NBF1 Local:[39.0, 126.0, 44.0, 4.0, 10.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Cost_of_Sales_without_Samples NBF1 USD:[39.0, 12.600000000000001, 8.8, 1.2000000000000002, 4.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] GP_Level_2 NBF1 Local:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] GP_Level_2 NBF1 USD:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Depletion_Allowance_Manual_Chargeback NBF1 Local:[39.0, 126.0, 44.0, 4.0, 10.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Depletion_Allowance_Manual_Chargeback NBF1 USD:[39.0, 12.600000000000001, 8.8, 1.2000000000000002, 4.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Regular_Cases NBF2 Local:[33.0, 32.0, 33.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Regular_Cases NBF2 USD:[33.0, 32.0, 33.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Net_Sales NBF2 Local:[1452.0, 1056.0, 1089.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Net_Sales NBF2 USD:[1452.0, 105.60000000000001, 217.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] GP_Level_1 NBF2 Local:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] GP_Level_1 NBF2 USD:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Cost_of_Sales_without_Samples NBF2 Local:[1452.0, 1056.0, 1089.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Cost_of_Sales_without_Samples NBF2 USD:[1452.0, 105.60000000000001, 217.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] GP_Level_2 NBF2 Local:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] GP_Level_2 NBF2 USD:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Depletion_Allowance_Manual_Chargeback NBF2 Local:[1452.0, 1056.0, 1089.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] Depletion_Allowance_Manual_Chargeback NBF2 USD:[1452.0, 105.60000000000001, 217.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] *** status Total number of cells accepted: 288 Total number of cells rejected: 0 First 100 rejected cells: [] Total number of cells accepted: 288 Total number of cells rejected: 0 First 100 rejected cells: [] ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 42. 42 DEMONSTRATION QUERYING METADATA • Process Segmentation » Execute processes only on a POV with data » Loop through metadata and execute processes • Currency Conversion » Identify whether the account should be converted to USD ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 43. 43 PROCESS SEGMENTATION Cube cube = operation.application.getCube("GP") Dimension companyDim = operation.application.getDimension("Company", cube) def Companies = companyDim.getEvaluatedMembers("ILvl0Descendants(tot_Company)", cube) as String[] def Currencies = ["Local","USD"] // Companies.each{company-> for (def i = 0; i < Companies.size(); i++) { def sCompanyItem = '"' + Companies[i] + ‘”’ // Currencies.each(currency -> for (def iCurrency = 0; iCurrency < Currencies.size(); iCurrency++){ def sCurrency = '"' + Currencies[iCurrency] + '"' operation.application.getDataMap("GP Form Push").execute (["Company":Companies[i],"Channel":"ILvl0Descendants(Channel)", "Material_Group":"ILvl0Descendants(Material_Group)", "Vendor":"ILvl0Descendants(Vendor)","Scenario":rtps.RTP_Scenario.getEssbaseValue(), "Version":"OEP_Working","Years":rtps.RTP_Year.getEssbaseValue(), "Source":"ILvl0Descendants(Source)","Currency":Currencies[iCurrency]], rtps.RTP_Push.getEssbaseValue().toBoolean()) elapsed=(currentTimeMillis()-procTime)/1000 procTime = currentTimeMillis() println "Push for Company $sCompanyItem, in ${Currencies[iCurrency]}: $elapsed seconds" } } elapsed=(currentTimeMillis()-procTime)/1000 procTime = currentTimeMillis() println "****************************************************" println "Time taken for allocation and consolidation = $elapsed secs" println "Total Time = " + (currentTimeMillis()-startTime)/1000 + " secs" println "****************************************************" ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 44. 44 CURRENCY CONVERSION boolean convertCurrency(def account='') { Dimension AccountDim = operation.application.getDimension("Account") Member AccountMbr = AccountDim.getMember(account) def memberProps = AccountMbr.toMap() if(memberProps['UDA'].toString().contains('IgnoreCurrencyConversion')) return false else return true } if(convertCurrency(account)){ [… do some action and convert the account (revenue * currency conversion rate)] } else{ [… do some action but don’t convert the account (headcount)] } ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 45. PRODUCTIVITY, GUIDANCE AND SUGGESTIONS Many people have challenges learning Groovy and the PBCS API at the same time. Here are some things that might help you get started ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend 45 6
  • 46. 46 SUGGESTIONS / TIPS • Get to know maps/collections/lists and how to manipulate them • Learn the inheritance of objects and how Groovy works with them • Understand how to read the API • Use closures anywhere you can • Grow your knowledge around string manipulation • Come up with a strategy to log the grid POV/headers/columns/data • .crossDimCell is your best friend I plan on posting detailed explainations of these at www.in2Hyperion.com in the near future, along with other use cases around Groovy knowledge ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 47. WHERE TO GO NEXT Need help? Here is a great place to start. 47 ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend 7
  • 48. 48 IN2HYPERION GROOVY SERIES • My Adventures in Groovy Calculations - Part 1 • Part 2: Data Validation • Part 3: Acting On Edited Cells • Part 4: Run Time Prompts • Part 5: Accessing Run Time Prompts • Part 6: Converting a POV into a Fix • Part 7: Validating Run Time Prompts • Part 8: Customizing Data Maps and Smart Pushes • Part 9: Groovy and PBCS is Game Changing in Louisville • Part 10: Validating Form Data • Part 11: Accessing Metadata Properties • Part 12: Learning and Testing Groovy Outside of PBCS • Part 13: Returning Errors (Data Forms) • Part 14: Returning Errors (Data Form Cells) • Part 15: Returning Errors (RTP Edition) add enhancement and other bug report • Part 16: Ignore Form Save When No Data Has Been Edited • Part 17: Force Cell Comments • Part 18: Real Time Data Movement (Setting The Stage) • Part 19: Real Time Reporting Webinar with Breakthru Beverage Group • Part 20: Groovy On-Premise vs. Groovy Cloud • Part 21: Real Time Data Movement (Getting Groovy) • Part 22: Looping Through Member Descendants • Part 23: Is the POV a level 0 member? • Part 24: Getting Member Properties? • Part 25: The DataGridBuilders • Part 26: Interacting with Smart Lists • Part 27: Using Maps in Groovy as lookup Tables ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 49. INSTRUCTIONAL VIDEOS • Real -Time Reporting in PBCS/ ePBCS • PBCS Require Comment - Groovy Calculation • Real Time Reporting Webinar • Groovy Examples: Webinar Follow-up I plan to supplement with more BLOG posts that include videos 49ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 50. 50 ORACLE AND GROOVY HOT SPOTS • PBCS Admin guide overview Using Groovy Rules. • Groovy rules Setting Business Rule Properties. • The Groovy API Reference on the E/PBCS library: • Java API Reference for Oracle Enterprise Performance Management Cloud Groovy Rules • The EPBCS Academy also links to the Groovy Rules Java API Reference hosted on the library. • Groovy Business Rule examples • There are a lot of great books, articles, videos on Groovy listed here: http://groovy-lang.org/learn.html • In particular, I would like to highlight the following two books: https://www.manning.com/books/groovy-in- action-second-edition https://pragprog.com/book/vslg2/programming- groovy-2 • The following course on Udemy is very affordable, and can be a useful asset: https://www.udemy.com/apache- groovy/learn/v4/overview • They can also start by going over the “Language Specification” section in the following document is also useful: http://groovy-lang.org/documentation.html
  • 51. OTHER SESSIONS Ask the Experts - Planning Panel Jun 12th, 2018 02:15 PM - 03:15 PM Southern Hemisphere II Top-Down and Bottom-Up Planning at Breakthru Beverage Group June 13th, 2018 11:45 AM - 12:45 PM Northern Hemisphere E3 Why Groovy is Game Changing June 13th, 2018, 3:30 PM - 4:30 PM Northern Hemisphere E3 Last Minute ODTUG Kscope18 Planning Souvenirs You Will ACTUALLY Use! June 14th, 9:30 - 11:00 a.m. Southern Hemisphere II 51ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 52. THAT’S A WRAP 52Groovy Grid Builder – Deep Dive • Kyle Goodfriend ODTUG • Kscope 18 8
  • 53. 53 A FEW PARTING GIFTS • Question & Answer Session • What would you like to see next at In2Hyperion.com? » Adventures in Groovy » Challenge Accepted Kyle Goodfriend kyle@in2hyperion.com 614.668.7324 ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend
  • 54. THANKS FOR ATTENDING Kyle Goodfriend kyle@in2hyperion.com 614.668.7324 ODTUG • Kscope 18 Groovy Grid Builder – Deep Dive • Kyle Goodfriend 54