Introducción

En este tutorial se muestra cómo implementar un script Groovy que valida la entrada de datos con respecto al rango permitido almacenado en un cubo de controladores.

Antecedentes

En este ejemplo, creará un script que se ejecutará cuando los usuarios guarden actualizaciones de salarios y bonificaciones de empleados desde un formulario de entrada de datos. El script carga los datos de grupo de empleado (salario mínimo/máximo permitido y bonificación mínima/máxima permitida) de un cubo de controlador en una cuadrícula temporal en la memoria y, a continuación, valida los valores de salario y bonificación introducidos en los rangos permitidos.

Requisitos

Los tutoriales prácticos de Cloud EPM pueden requerir que importe una instantánea en su instancia de Cloud EPM Enterprise Service. Antes de importar una instantánea de tutorial, debe solicitar otra instancia de Cloud EPM Enterprise Service o eliminar la aplicación y el proceso de negocio actuales. La instantánea del tutorial no se importará a través de su aplicación o proceso de negocio existente, ni reemplazará o restaurará automáticamente la aplicación o el proceso de negocio con el que está trabajando actualmente.

Antes de comenzar este tutorial, debe:

  • Tener acceso de administrador de servicio a una instancia de Cloud EPM Enterprise Service.
  • Cargue e importe esta instantánea en la instancia de Planning. Si ha cargado previamente la instantánea de otro tutorial de Groovy, puede continuar utilizando la misma instantánea.

Note:

Si se producen errores de migración al importar la instantánea, vuelva a ejecutar la migración excluyendo el componente de HSS-Shared Services, así como los artefactos de seguridad y preferencias de usuario en el componente Core. Para obtener más información sobre la carga y la importación de instantáneas, consulte la documentación de Administración de migración para Oracle Enterprise Performance Management Cloud.

Sugerencia:

Los scripts que necesita para este tutorial están enlazados como archivos de texto dentro de cada sección.

Creación del script

  1. Abra Calculation Manager y cree una regla denominada Validar datos de empleado de Groovy en el cubo Plan1.
  2. Nuevo Objeto
  3. En el editor de reglas, cambie la opción Diseñador a Editar script y defina el tipo de script en Script de Groovy.
  4. Opciones del editor de reglas
  5. Copie esta secuencia de comandos y péguela en el editor.
  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. En la barra de herramientas, haga clic en Guardar (Guardar) para guardar el script y, a continuación, haga clic en Validar y desplegar (Validar y desplegar) para validar y desplegar el script. Haga clic en OK (Aceptar) cuando se le solicite. Cierre Calculation Manager.

Explicación de la Lógica del Script

En esta sección, describiremos la lógica del script de una sección a la vez.

  1. Crear una clase.

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

    Cree una clase, GradeData, para almacenar los datos de grupo de empleados (salario mínimo/máximo permitido y bonificación mínima/máxima permitida) desde un cubo de controlador.

    El método toString() devuelve una representación de cadena del objeto GradeData. El método utiliza el operador seguro nulo (?.) proporcionado por Groovy. Si la variable anterior al signo de interrogación es nula, no continuará y devolverá NULL. Por ejemplo, {minSalary?.formattedValue} se evalúa en el valor NULL en lugar de devolver una excepción NullPointerException si minSalary es nulo.

  2. Cree un cargador de paquetes.
  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() 
    

    Cree un cargador de grupo de recursos que contenga los mensajes localizados que necesita esta regla.

    Obtener el cubo de controlador/consulta.

    Obtenga un DataGridDefinitionBuilder para el cubo. Utilice el creador para crear una región a partir de la cual cargar los datos agregando los miembros de PDV, los miembros de columna y las filas.

    Cree el objeto DataGridDefinition.

  4. Cargue la cuadrícula de datos del cubo de consulta para la región definida por el objeto DataGridDefinition.
  5. DataGrid dataGrid = lookupCube.loadGrid(gridDefinition, false)  
  6. Cree una asignación de datos de grupo (salario mínimo/máximo y bonificación) por nombre de grupo desde la cuadrícula de datos.
    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)
        }
    }

    Cree una asignación denominada gradeDataMap de datos de grupo (salario mínimo/máximo y bonificación) por nombre de grupo.

    Rellene el mapa gradeDataMap con los datos de grupo de cada grupo. El grado es la clave y el objeto GradeData relleno con el salario mínimo/máximo y el bono es el valor.

  7. Cree un iterador que itere en todas las celdas de datos que contengan el miembro Grade en la cuadrícula de entrada actual.
  8. DataGrid grid = operation.grid
    GridIterator itr = grid.dataCellIterator('Grade')
  9. Lanzar una excepción de veto.
  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")
    }

    Valide que la cuadrícula de entrada tenga al menos una celda que contenga el miembro de grupo. Si no es así, devuelva una excepción de veto con el mensaje localizado.

  11. Valide los valores de cuadrícula.
  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.")  
            }
        }
    }

    Valide los valores de la cuadrícula de entrada que se guardan en los valores de gradeDataMap. El grupo de la cuadrícula de entrada es una cuenta de tipo lista inteligente que se deriva de la jerarquía de grupos definida en el cubo de consulta. Al llamar a it.DataAsSmartListMemberName, se obtiene el nombre del miembro del que se deriva el valor de la lista inteligente de la celda actual, que se puede utilizar como clave en el mapa para obtener los datos de calificación.

    Disminución cruzada en la celda Salario y validación del salario con el salario permitido en los datos de grado.

    Reducir atenuación en la celda Bonificación y validar la bonificación con respecto a la bonificación permitida en los datos de calificación. Si el salario o la bonificación no están dentro de los límites permitidos, defina el color de fondo de la celda en rojo y agregue un error de validación en la celda llamando a la API addValidationError(). El mensaje de error se establecerá como pista de la celda y también se mostrará en los mensajes de validación de cuadrícula. Además, si esta regla se ejecuta después de guardar, el sistema vetará la operación de guardado.

Prueba del script

  1. En el gestor de formularios, edite el formulario ManageEmployees y asocie la regla Validar datos de empleado de Groovy para que se ejecute Después de la carga y Antes de guardar (puede que primero tenga que seleccionar Plan1 en la lista Cubo).
  2. El formulario ManageEmployees con la regla asociada.
  3. Guarde el formulario y cierre la ventana del Gestor de formularios.
  4. Abra el panel de control Empleados. Agregue una bonificación de 1000 para el empleado 1 y aumente el salario del empleado 2 a 65000. En la barra de Herramientas del formulario, haga clic en Guardar (Guardar).
  5. El panel de control Empleados.
  6. En el cuadro de diálogo de mensaje de error, haga clic en OK (Aceptar).
  7. El panel de control Empleados.
  8. Pase el mouse sobre los glóbulos rojos para ver los mensajes de error detallados como pistas.

    Mensaje de error.

    Mensaje de error.

  9. Cierre el panel de control y abra la consola Trabajos.
  10. Panel Actividad reciente de la Consola de trabajos.
  11. Haga clic en Validar datos de empleado de Groovy para mostrar los detalles del trabajo. Haga clic en el estado Finalizado para ver los datos de grupo cargados desde el cubo de consulta y los datos de grupo según el grupo de cada empleado.
  12. Los mensajes del log.

Más recursos de aprendizaje

Explore otros laboratorios en docs.oracle.com/learn o acceda a más contenido de aprendizaje gratuito en el canal YouTube de Oracle Learning. Además, visite Oracle University para ver los recursos de formación disponibles.

Para obtener documentación sobre el producto, visite Oracle Help Center.