소개
이 자습서에서는 드라이버 큐브에 저장된 허용 범위에 대해 데이터 입력을 검증하는 Groovy 스크립트를 구현하는 방법을 보여줍니다.
배경
이 예에서는 사용자가 데이터 입력 양식에서 사원 임금 및 상여에 대한 업데이트를 저장할 때 실행되는 스크립트를 생성합니다. 이 스크립트는 사원 등급 데이터(최소/최대 허용 임금 및 최소/최대 허용 상여금)를 드라이버 큐브에서 메모리의 임시 그리드로 로드한 다음 입력된 임금 및 상여금 값을 허용된 범위에 대해 검증합니다.
필요 조건
Cloud EPM 실습 자습서에서는 Cloud EPM Enterprise Service 인스턴스로 스냅샷을 임포트해야 할 수 있습니다. 자습서 스냅샷을 임포트하려면 먼저 다른 Cloud EPM Enterprise Service 인스턴스를 요청하거나 현재 애플리케이션 및 비즈니스 프로세스를 제거해야 합니다. 자습서 스냅샷은 기존 애플리케이션 또는 비즈니스 프로세스로 가져오지 않으며 현재 작업 중인 애플리케이션 또는 비즈니스 프로세스를 자동으로 바꾸거나 복원하지 않습니다.
이 자습서를 시작하기 전에 다음을 수행해야 합니다.
- Cloud EPM Enterprise Service 인스턴스에 대한 서비스 관리자에게 접근 권한을 부여합니다.
- 이 스냅샷을 업로드하여 Planning 인스턴스로 임포트합니다. 이전에 다른 Groovy 자습서에 대한 스냅샷을 업로드한 경우 동일한 스냅샷을 계속 사용할 수 있습니다.
주:
스냅샷을 임포트하는 마이그레이션 오류가 발생하는 경우 HSS-Shared Services 구성요소는 물론 코어 구성요소의 보안 및 사용자 환경설정 아티팩트를 제외한 마이그레이션을 다시 실행합니다. 스냅샷 업로드 및 임포트에 대한 자세한 내용은 Oracle Enterprise Performance Management Cloud용 마이그레이션 관리 설명서를 참조하십시오.참고:
이 자습서에 필요한 스크립트는 각 섹션의 텍스트 파일로 링크됩니다.스크립트 생성
- Calculation Manager를 열고 Plan1 큐브에 Groovy 직원 데이터 검증이라는 규칙을 생성합니다.
- 규칙 편집기에서 디자이너 옵션을 스크립트 편집으로 변경하고 스크립트 유형을 Groovy 스크립트로 설정합니다.
- 이 스크립트를 복사하여 편집기에 붙여 넣습니다.
- 도구 모음에서
(저장)을 눌러 스크립트를 저장한 다음
(검증 및 배치)을 눌러 스크립트를 검증하고 배치합니다. 프롬프트가 표시되면 확인을 누릅니다. Calculation Manager를 닫습니다.


class GradeData { Integer Grade DataGrid.DataCell minSalary DataGrid.DataCell maxSalary DataGrid.DataCell minBonus DataGrid.DataCell maxBonus public String toString() { return "minSalary: ${minSalary?.formattedValue}, maxSalary: ${maxSalary?.formattedValue}, minBonus: ${minBonus?.formattedValue}, maxBonus: ${maxBonus?.formattedValue}" } } // Create a resource bundle loader containing localized messages needed by this rule. def mbUs = messageBundle( ["validation.missingmember.grade":"No Grades found on the Grid."] ) def mbl = messageBundleLoader(["en" : mbUs]) Cube lookupCube = operation.application.getCube("Plan1") DataGridDefinitionBuilder builder = lookupCube.dataGridDefinitionBuilder() builder.addPov(['Years', 'Scenario', 'Currency', 'Period', 'Version', 'Entity'], [['FY16'], ['Current'], ['USD'], ['BegBalance'], ['BU Version_1'], ['No Entity']]) builder.addColumn(['Account'], [ ['Min Salary', 'Max Salary', 'Min Bonus', 'Max Bonus'] ]) builder.addRow(['Grades'], [ ['ILvl0Descendants("Grades")'] ]) DataGridDefinition gridDefinition = builder.build() // Load the data grid from the lookup cube DataGrid dataGrid = lookupCube.loadGrid(gridDefinition, false) // Create a map of grade data (Min/Max Salary and Bonus) by grade name from the data grid. def gradeDataMap = new HashMap() if(dataGrid) { println("dataGrid is not null") dataGrid.dataCellIterator('Min Salary').each { def gradeData = new GradeData() gradeData.minSalary = it gradeData.maxSalary = it.crossDimCell('Max Salary') gradeData.minBonus = it.crossDimCell('Min Bonus') gradeData.maxBonus = it.crossDimCell('Max Bonus') gradeDataMap[(it.getMemberName('Grades'))] = gradeData println(it.getMemberName('Grades') + ": " + gradeData) } } DataGrid grid = operation.grid // Construct an iterator that iterates over all data cells containing the Grade member. GridIterator itr = grid.dataCellIterator('Grade') // Throw a veto exception if the grid has at least one cell but does not contain any cells containing the Grade member. if(!grid.empty && !itr.hasNext()) { // Found 0 cells with Grade throwVetoException(mbl, "validation.missingmember.grade") } // Validate the values in the grid being saved against the values in gradeDataMap. itr.each { GradeData gradeData = gradeDataMap[it.DataAsSmartListMemberName] if(gradeData == null) { println("Unable to locate grade data for grade: ${it.DataAsSmartListMemberName}, with data value: ${it.formattedValue}" ) } else { println(it.getMemberName('Employee') + ": " + gradeData.toString()) DataCell salary = it.crossDimCell('Salary') if(salary == null) println("Unable to locate Salary") else if(salary.data < gradeData.minSalary.data || salary.data > gradeData.maxSalary.data) { salary.addValidationError(0xFF0000, "Salary is outside of the allowed range.") } DataCell bonus = it.crossDimCell('Bonus') if(bonus == null) { println("Unable to locate Bonus") } else if(bonus.data < gradeData.minBonus.data || bonus.data > gradeData.maxBonus.data) { bonus.addValidationError(0xFF0000, "Bonus is outside of the allowed range.") } } }
스크립트 논리 설명
이 섹션에서는 스크립트 논리를 한 번에 한 섹션씩 설명합니다.
-
클래스를 생성합니다.
class GradeData {
Integer Grade DataGrid.DataCell minSalary DataGrid.DataCell maxSalary DataGrid.DataCell minBonus DataGrid.DataCell maxBonus public String toString() { return "minSalary: ${minSalary?.formattedValue}, maxSalary: ${maxSalary?.formattedValue}, minBonus: ${minBonus?.formattedValue}, maxBonus: ${maxBonus?.formattedValue}"
} }
드라이버 큐브에서 직원 등급 데이터(최소/최대 허용 임금 및 최소/최대 허용 상여금)를 저장할 클래스
GradeData
를 생성합니다.toString()
메소드는GradeData
객체의 문자열 표현을 반환합니다. 이 메소드는 Groovy에서 제공하는 널 안전 연산자(?.
)를 사용합니다. 물음표 앞의 변수가 널이면 진행되지 않고NULL
를 반환합니다. 예를 들어,minSalary
가 널인 경우NullPointerException
예외를 발생시키는 대신{minSalary?.formattedValue}
가NULL
값으로 평가됩니다. - 번들 로더를 생성합니다.
- DataGridDefinition 객체로 정의된 영역에 대한 룩업 큐브에서 데이터 그리드를 로드합니다.
- 데이터 그리드에서 등급 이름별로 등급 데이터(최소/최대 임금 및 상여)의 맵을 생성합니다.
def gradeDataMap = new HashMap<String, GradeData>()
if(dataGrid) { println("dataGrid is not null") dataGrid.dataCellIterator('Min Salary').each {
def gradeData = new GradeData() gradeData.minSalary = it gradeData.maxSalary = it.crossDimCell('Max Salary') gradeData.minBonus = it.crossDimCell('Min Bonus') gradeData.maxBonus = it.crossDimCell('Max Bonus') gradeDataMap[(it.getMemberName('Grades'))] = gradeData println(it.getMemberName('Grades') + ": " + gradeData) } }
등급 이름별로 등급 데이터(최소/최대 임금 및 상여)의
gradeDataMap
라는 맵을 생성합니다.gradeDataMap
맵을 각 등급에 대한 등급 데이터로 채웁니다. 등급은 키이며 GradeData 객체는 최소/최대 임금으로 채워지고 상여는 값입니다. - 현재 입력 그리드의 등급 멤버를 포함하는 모든 데이터 셀에 대해 반복되는 이터레이터를 구성합니다.
- 거부 예외를 발생시킵니다.
- 그리드 값을 검증합니다.
// Create a resource bundle loader containing localized messages needed by this rule. def mbUs = messageBundle( ["validation.missingmember.grade":"No Grades found on the Grid."] )def mbl = messageBundleLoader(["en" : mbUs]) Cube lookupCube = operation.application.getCube("Plan1")
DataGridDefinitionBuilder builder = lookupCube.dataGridDefinitionBuilder()
builder.addPov(['Years', 'Scenario', 'Currency', 'Period', 'Version', 'Entity'], [['FY16'], ['Current'], ['USD'], ['BegBalance'], ['BU Version_1'], ['No Entity']]) builder.addColumn(['Account'], [ ['Min Salary', 'Max Salary', 'Min Bonus', 'Max Bonus'] ]) builder.addRow(['Grades'], [ ['ILvl0Descendants("Grades")'] ]) DataGridDefinition gridDefinition = builder.build()
![]()
이 규칙에 필요한 현지화된 메시지가 포함된 리소스 번들 로더를 만듭니다.
드라이버/검색 큐브를 가져옵니다.
큐브에 대한 DataGridDefinitionBuilder를 가져옵니다. 빌더를 사용하여 POV 멤버, 열 멤버 및 행을 추가하여 데이터를 로드할 영역을 생성합니다.
DataGridDefinition 객체를 작성합니다.
DataGrid dataGrid = lookupCube.loadGrid(gridDefinition, false)
DataGrid grid = operation.grid GridIterator itr = grid.dataCellIterator('Grade')
// Throw a veto exception if the grid has at least one cell but does not contain any cells containing the Grade member. if(!grid.empty && !itr.hasNext()) {// Found 0 cells with Grade throwVetoException(mbl, "validation.missingmember.grade") }
입력 그리드에 등급 멤버를 포함하는 셀이 하나 이상 있는지 검증합니다. 그렇지 않은 경우 지역화된 메시지와 함께 거부 예외를 발생시킵니다.
// Validate the values in the grid being saved against the values in gradeDataMap. itr.each {GradeData gradeData = gradeDataMap[it.DataAsSmartListMemberName] if(gradeData == null) { println("Unable to locate grade data for grade: ${it.DataAsSmartListMemberName}, with data value: ${it.formattedValue}" ) } else { println(it.getMemberName('Employee') + ": " + gradeData.toString()) DataCell salary = it.crossDimCell('Salary')
if(salary == null) println("Unable to locate Salary") else if(salary.data < gradeData.minSalary.data || salary.data > gradeData.maxSalary.data) { salary.addValidationError(0xFF0000, "Salary is outside of the allowed range.") } DataCell bonus = it.crossDimCell('Bonus')
if(bonus == null) { println("Unable to locate Bonus") } else if(bonus.data < gradeData.minBonus.data || bonus.data > gradeData.maxBonus.data) { bonus.addValidationError(0xFF0000, "Bonus is outside of the allowed range.") } } }
gradeDataMap의 값에 대해 저장하려는 입력 그리드의 값을 검증합니다. 입력 그리드의 등급은 룩업 큐브에 정의된 등급 계층에서 파생된 스마트 목록 유형의 계정입니다.
it.DataAsSmartListMemberName
를 호출하면 현재 셀의 스마트 목록 값이 파생되는 멤버의 이름을 가져오고, 이 이름을 맵의 키로 사용하여 등급 데이터를 가져올 수 있습니다.
임금 셀로 교차하여 등급 데이터의 허용된 임금에 대해 임금을 검증합니다.
보너스 셀로 교차하여 등급 데이터의 허용된 보너스에 대해 보너스를 검증합니다. 임금 또는 상여가 허용된 한도 내에 있지 않은 경우 셀의 배경색을 빨간색으로 설정하고
addValidationError()
API를 호출하여 셀에 검증 오류를 추가합니다. 오류 메시지는 셀의 도구 설명으로 설정되며 그리드 검증 메시지에도 표시됩니다. 또한 이 규칙이 저장 후 실행되는 경우 시스템에서 저장 작업을 거부합니다.
스크립트 테스트
- 양식 관리자에서 ManageEmployees 양식을 편집하고 Groovy 직원 데이터 검증 규칙을 연계하여 로드 후 및 저장 전을 실행합니다(큐브 목록에서 먼저 Plan1을 선택해야 할 수 있음).
- form을 저장하고 Form Manager window를 닫습니다.
- 직원 대시보드를 엽니다. 사원 1에 대한 상여금 1000을 추가하고 사원 2에 대한 급여를 65000으로 늘립니다. 양식 도구모음에서
(저장)을 누릅니다.
- 오류 메시지 대화 상자에서 확인을 누릅니다.
- 빨간색 셀 위로 마우스를 가져가면 자세한 오류 메시지가 도구 설명으로 표시됩니다.
- 대시보드를 닫고 Jobs 콘솔을 엽니다.
- 직원 데이터 확인을 눌러 직무 세부정보를 표시합니다. 완료됨 상태를 눌러 룩업 큐브에서 로드된 등급 데이터와 각 사원의 등급별 등급 데이터를 확인합니다.





관련 링크
추가 학습 자원
docs.oracle.com/learn에서 다른 랩을 탐색하거나 Oracle Learning YouTube 채널에서 더 많은 무료 학습 콘텐츠에 액세스하세요. 또한 제공되는 교육 리소스를 보려면 Oracle University를 방문하십시오.
제품 설명서는 Oracle Help Center를 참조하십시오.