Einführung

In diesem Tutorial wird gezeigt, wie Sie ein Groovy-Skript zur Validierung der Dateneingabe anhand in einem Treiber-Cube gespeicherter zulässiger Bereiche implementieren.

Hintergrund

In diesem Beispiel erstellen Sie ein Skript, das ausgeführt wird, wenn Benutzer Aktualisierungen der Mitarbeitergehälter und -boni aus einem Dateneingabeformular speichern. Das Skript lädt Mitarbeitergehaltsgruppendaten (Mindest-/Höchstgehalt und zulässiger Mindest-/Höchstzuschlag) aus einem Treiber-Cube in ein temporäres Grid im Speicher und validiert dann die eingegebenen Gehalts- und Bonuswerte anhand der zulässigen Bereiche.

Voraussetzungen

Für praktische Tutorials zu Cloud EPM müssen Sie möglicherweise einen Snapshot in Ihre Cloud EPM Enterprise Service-Instanz importieren. Bevor Sie einen Tutorial-Snapshot importieren können, müssen Sie eine andere Cloud EPM Enterprise Service-Instanz anfordern oder Ihre aktuelle Anwendung und Ihren aktuellen Geschäftsprozess entfernen. Der Tutorial-Snapshot wird weder über Ihre vorhandene Anwendung oder Ihren vorhandenen Geschäftsprozess importiert, noch wird er die Anwendung oder den Geschäftsprozess, mit dem Sie derzeit arbeiten, automatisch ersetzen oder wiederherstellen.

Bevor Sie mit diesem Tutorial beginnen, müssen Sie:

  • Haben Sie Serviceadministratorzugriff auf eine Cloud EPM Enterprise Service-Instanz.
  • Laden Sie diesen Snapshot hoch, und importieren Sie ihn in Ihre Planning-Instanz. Wenn Sie das Snapshot zuvor für ein anderes Groovy-Tutorial hochgeladen haben, können Sie den gleichen Snapshot weiterhin verwenden.

Hinweis:

Wenn beim Importieren des Snapshots Migrationsfehler auftreten, führen Sie die Migration erneut aus, ausgenommen die HSS-Shared Services-Komponente sowie die Artefakte der Sicherheits- und Benutzervoreinstellungen in der Core-Komponente. Weitere Informationen zum Hochladen und Importieren von Snapshots finden Sie in der Dokumentation Migration für Oracle Enterprise Performance Management Cloud verwalten.

Tipp:

Die Skripte, die Sie für dieses Tutorial benötigen, sind in jedem Abschnitt als Textdateien verknüpft.

Skript erstellen

  1. Öffnen Sie Calculation Manager, und erstellen Sie eine Regel namens Groovy Validate Employee Data im Cube Plan1.
  2. Neues Objekt
  3. Ändern Sie im Regeleditor die Designeroption in Skript bearbeiten, und setzen Sie den Skripttyp auf Groovy-Skript.
  4. Regeleditoroptionen
  5. Kopieren Sie dieses Skript und fügen Sie es in den Editor hinzu.
  6. 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.")  
            }
        }
    }
    
  7. Klicken Sie in der Symbolleiste auf Speichern (Speichern), um das Skript zu speichern, und klicken Sie dann auf Validieren und Bereitstellen (Validieren und bereitstellen), um das Skript zu validieren und bereitzustellen. Klicken Sie auf OK, wenn Sie dazu aufgefordert werden. Schließen Sie Calculation Manager.

Skriptlogik erläutern

In diesem Abschnitt wird die Skriptlogik nacheinander beschrieben.

  1. Erstellen einer Klasse.

    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}" 
        }
    }

    Erstellen Sie eine Klasse, GradeData, um die Mitarbeitergehaltsgruppendaten (Mindest-/Höchstgehalt und zulässiger Mindest-/Höchstbonus) aus einem Treiber-Cube zu speichern.

    Die Methode toString() gibt eine Zeichenfolgendarstellung des Objekts GradeData zurück. Die Methode verwendet den Null-sicheren Operator (?.), der von Groovy bereitgestellt wird. Wenn die Variable vor dem Fragezeichen Null ist, wird sie nicht fortgesetzt und gibt NULL zurück. Beispiel: {minSalary?.formattedValue} ergibt den Wert NULL, anstatt eine NullPointerException-Ausnahme auszulösen, wenn minSalary null ist.

  2. Erstellen Sie einen Bundle Loader.
  3. // 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() 
    

    Erstellen Sie einen Resource Bundle Loader mit lokalisierten Nachrichten, die von dieser Regel benötigt werden.

    Holen Sie sich den Driver/Lookup Cube.

    Rufen Sie eine DataGridDefinitionBuilder für den Cube ab. Mit dem Builder können Sie einen Bereich erstellen, aus dem die Daten geladen werden sollen, indem Sie die POV-Elemente, Spaltenelemente und Zeilen hinzufügen.

    Erstellen Sie das Objekt DataGridDefinition.

  4. Laden Sie das Datenraster aus dem Lookup-Cube für die durch das Objekt DataGridDefinition definierte Region.
  5. DataGrid dataGrid = lookupCube.loadGrid(gridDefinition, false)  
  6. Auf dieser Seite erstellen Sie eine Zuordnung von Gehaltsgruppendaten (Min/Max Gehalt und Bonus) nach Gehaltsgruppenname aus dem Daten-Grid.
    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)
        }
    }

    Erstellen Sie eine Zuordnung mit dem Namen gradeDataMap der Gehaltsgruppendaten (Min/Max Gehalt und Bonus) nach Gehaltsgruppenname.

    Füllen Sie die Zuordnung gradeDataMap mit den Gehaltsgruppendaten für jede Gehaltsgruppe auf. "Stufe" ist der Schlüssel, und das Objekt GradeData, das mit "Min/Max Gehalt" und "Bonus" aufgefüllt wird, ist der Wert.

  7. Erstellen Sie einen Iterator, der über alle Datenzellen iteriert, die das Grade-Element im aktuellen Eingaberaster enthalten.
  8. DataGrid grid = operation.grid
    GridIterator itr = grid.dataCellIterator('Grade')
  9. Wirf ein Veto-Ausnahme.
  10. // 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")
    }

    Stellen Sie sicher, dass das Eingaberaster mindestens eine Zelle mit dem Gehaltsgruppenelement enthält. Falls nicht, werfen Sie eine Veto-Ausnahme mit der lokalisierten Meldung aus.

  11. Grid-Werte validieren
  12. // 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.")  
            }
        }
    }

    Validieren Sie die Werte im Eingaberaster, die für die Werte in gradeDataMap gespeichert werden. Die Gehaltsgruppe im Eingaberaster ist ein Konto des Typs "Smart List", das aus der Gehaltsgruppenhierarchie abgeleitet wird, die im Lookup-Cube definiert ist. Beim Aufruf von it.DataAsSmartListMemberName wird der Name des Elements abgerufen, aus dem der Smart List-Wert der aktuellen Zelle abgeleitet wird. Dieser kann dann als Schlüssel in der Zuordnung verwendet werden, um die Gehaltsgruppendaten abzurufen.

    Wechseln Sie in die Zelle "Gehalt", und validieren Sie das Gehalt anhand des zulässigen Gehalts in den Gehaltsgruppendaten.

    Blenden Sie die Dimension in die Zelle "Bonus" ein, und validieren Sie den Bonus anhand des zulässigen Bonus in den Gehaltsgruppendaten. Wenn das Gehalt oder der Bonus nicht innerhalb der zulässigen Grenzen liegt, setzen Sie die Hintergrundfarbe der Zelle auf rot, und fügen Sie einen Validierungsfehler in der Zelle hinzu, indem Sie die API addValidationError() aufrufen. Die Fehlermeldung wird als QuickInfo für die Zelle festgelegt und auch in den Grid-Validierungsmeldungen angezeigt. Wenn diese Regel nach dem Speichern ausgeführt wird, wird der Speichervorgang vom System abgelehnt.

Skript testen

  1. Bearbeiten Sie im Formularmanager das Formular ManageEmployees, und verknüpfen Sie die Groovy-Regel "Mitarbeiterdaten validieren", die nach dem Laden und Vor dem Speichern ausgeführt werden soll. (Sie müssen möglicherweise zuerst Plan1 aus der Cube-Liste auswählen.)
  2. Das Formular ManageEmployees mit der verknüpften Regel.
  3. Speichern Sie das Formular, und schließen Sie das Fenster "Formularmanager".
  4. Öffnen Sie das Dashboard Mitarbeiter. Fügen Sie einen Bonus von 1000 für Mitarbeiter 1 hinzu, und erhöhen Sie das Gehalt für Mitarbeiter 2 auf 65000. Klicken Sie in·der Symbolleiste des Formulars auf Speichern (Speichern).
  5. Das Dashboard "Mitarbeiter".
  6. Klicken Sie im Dialogfeld "Fehlermeldung" auf OK.
  7. Das Dashboard "Mitarbeiter".
  8. Bewegen Sie den Mauszeiger über die roten Zellen, um die detaillierten Fehlermeldungen als QuickInfos anzuzeigen.

    Die Fehlermeldung.

    Die Fehlermeldung.

  9. Schließen Sie das Dashboard, und öffnen Sie die Konsole "Jobs".
  10. Der Bereich "Letzte Aktivität" der Jobkonsole.
  11. Klicken Sie auf Groovy - Mitarbeiterdaten validieren, um die Jobdetails anzuzeigen. Klicken Sie auf den Status Abgeschlossen, um die Gehaltsgruppendaten anzuzeigen, die aus dem Lookup-Cube geladen wurden, sowie die Gehaltsgruppendaten für die Gehaltsgruppe jedes Mitarbeiters.
  12. Die Logmeldungen.

Weitere Lernressourcen

Sehen Sie sich weitere Übungen zu docs.oracle.com/learn an, oder greifen Sie auf weitere kostenlose Lerninhalte im Oracle Learning YouTube-Kanal zu. Besuchen Sie außerdem Oracle University, um verfügbare Schulungsressourcen anzuzeigen.

Die Produktdokumentation finden Sie im Oracle Help Center.