martes, 19 de julio de 2011

Cómo hacer cuadros de mando: V

Implementación con Pentaho y CDE


Tras muchas consideraciones teóricas por fin vamos a hacer nuestro primer cuadro de mandos con Pentaho y CDE. Comunity Dashboard Editor es un editor de cuadros de mando desarrollado por la comunidad de Pentaho, mas concretamente por la excelente empresa portuguesa Webdetails liderada por Pedro Alves.

Realmente CDE es un editor de cuadros de mando a través de una interfaz web gráfica e intuitiva aunque es mucho mas que eso. Es la culminación de un proceso que empezó con:
  • CDF (Comunity Dashboard Framework): Framework de desarrollo que permitía hacer cuadros de mando mediante html y javascript. Todo un avanze en el momento que salió cuando yo los hacía programando páginas JSP.
  • CDA (Comunity Data Access) : Framework que permite el acceso a los datos de una forma mas cómoda y elegante. Permite además cachear consultas para que estén previamente calculadas y jugar e interactuar con diferentes orígenes de datos.
  • CCC (Comunity Chart Component): Cualquier persona que haya desarrollado para la web sabe que manejar el aspecto visual, tan importante en nuestro desarrollo, es un dolor de cabeza constante debido a la diversidad de navegadores. Comunity Chart Component nos permite abstraernos de todos esos problemas y centrarnos en lo que realmente importa: La visualización de nuestros datos.  El Comunity Chart Component se basa en la librería de gráficos JavaScript Protovis.
  • C ? ? : Pedro AlvesWebdetails son muy activos y nunca se sabe con que mejora nos van a sorprender. 
 Para hacer este cuadro de mandos voy a utilizar Pentaho BI Server CE 3.8 que se encuentra libremente disoponible en SourceForge y el conjunto de herramientas C * * que me proporcionarán todo el entorno de desarrollo y que Pedro nos facilita su instalación mediante este cómodo script.



Primer paso: Saber qué es lo que quiero


Seguramente nuestro Cuadro de mandos dará muchas vueltas y tendrá muchas modificaciones a lo largo de su vida útil, pero necesitamos un punto de partida y ese punto de partida suele ser 2 cosas:
  • Listado de los KPI a incluir
  • Boceto de visualización
Mi cuadro de mandos se basa en el ejemplo Quadrant Analysis que viene incluido como ejemplo con Pentaho BI server. Por lo que voy a hacer un cuadro de mando que me permita comparar Presupuestos contra el gasto.



Mi cuadro de mandos: Estado de las cuentas: Presupuesto Vs Gastos

Mis KPI:
  • Estado del presupuesto...
    • Por departamento
    • Por cargos
  • Quien se desvía mas del presupuesto...
    • Por arriba (Se pasa)
    • Por abajo (Gasta menos de lo presupuestado... a estos hay que felicitarlos)
Ya tengo mis indicadores... ahora vamos a ver cómo quiero visualizarlos.

Y finalmente, decidir que interacción le vamos a dar a nuestro cuadro de mandos...  en este primer cuadro de mandos vamos a hacerlo simple y tan sólo vamos a permitir ver las diferentes posiciones  en cada departamento.



Segundo paso: Implementemos nuestro diseño


CDE está diseñado  en 3 capas: Presentación, Componentes y Datos.


Presentación


Empecemos diseñando la presentación, cómo se va a ver nuestro cuadro de mandos.

Tenemos 2 opciones:

  1. Aplicar una plantilla
  2. Definir Nosotros el aspecto, que es lo que vamos a hacer.

La forma de diseñar el cuadro de mandos es "como se hacían antes las páginas web, definir una rejilla de lineas y columnas y colocando los objetos dentro".  Por lo que si volvemos a ver nuestro cuadro de mandos podemos extraer la siguiente estructura:
 Líneas = Rows
Cajas = Columns.


Debemos, también tener en cuenta que CDE se basa en el framework CSS BluePrint por lo que el ancho máximo de la página disponible será 24. Si queremos hacer 2 columnas 12 y 12, así sucesivamente.

Vamos pues a realizar la plantilla de nuestro cuadro de mandos:



Llenado de Contenido


Una vez que tenemos la plantilla de nuestro cuadro de mandos empecemos a llenarla de contenido. Primero  el origen de datos y luego la gráfica en cuestión. Para ello, lo primero que haremos será realizar la consulta en el visor OLAP. Una vez tengamos la consulta que queremos y esta nos retorne los datos que deseamos la utilizaremos en nuestro cuadro de mandos.
Iremos a la pestaña de Data Sources donde se encuentran una gran variedad de orígenes de datos posibles. A mi, personalmente me gusta utilizar los cubos OLAP que ya tenemos definidos por lo que haremos un nuevo orígen de datos MDX Query  y MDX over JNDI . Cabe destacar que CDE incluye en muchos sitios un utilísimo auto completado y que se invoca presionando la tecla de cursor hacia abajo ( ↓ ). 

Una vez que tengamos listo nuestro origen de datos es la hora de crear el gráfico. El gráfico se encuentra en la pestaña Components  donde encontraremos un gran número de componentes. Nosotros nos vamos a centrar en los Charts y más concretamente en el CCC Bar Chart . Cabe destacar que mas allá de los atributos normales de un gráfico, podemos ir a las "advanced properties" que nos permitirán hacer una multitud de cosas con los gráficos disponibles.



Para tener nuestro primer gráfico hemos:

  1. Definido un origen de datos del tipo MDX  y en concreto MDX over Mondrian JNDI 
    1. El nombre del origen de datos que vamos a utilizar es Departamento_DS
    2. El origen de datos es sobre el schema SampleData que usa el JNDI SampleData
    3. La consulta que vamos a utilizar es una que nos permitirá ver el actual y el budget para toda la empresa unido al detallado para cada departamento:


      select NON EMPTY {[Measures].[Actual], [Measures].[Budget]} ON COLUMNS,
      NON EMPTY Hierarchize(Union({[Department].[All Departments]}, [Department].[All Departments].Children)) ON ROWS
      from [Quadrant Analysis]


  2. Definimos un componente que utiliza ese origen de datos:
    1. El componente es un chart
    2. Concretamente es un CCC Bar Chart
    3. Definimos un alto y un ancho para el gráfico.
    4. Definimos el origen de datos (datasource) de ese gráfico como el que acabamos de definir  Departamento_DS 
    5. Le decimos que viene de una Crosstab
    6. Definimos el objeto html ( HtmlObject ) donde ubicaremos nuestro gráfico. El contenedor que hemos preparado en la plantilla de visualización
    7. Finalmente, en las propiedades avanzadas ( AdvancedProperties ) definimos que la orientación es horizontal para que se vea un poco mejor y ampliamos el tamaño que tendrá el eje de las Y (  YY axis size ) para que los nombres puedan caber 

Ahora vamos a por nuestro segundo gráfico, el que nos permitirá analizar la desviación entre el presupuesto y el gasto real en función de los diferentes rangos laborales. El procedimiento es fundamentalmente el mismo. En este caso vamos a utilizar un gráfico del tipo CCC Dot Chart que nos proporcionará una vista más limpia que un gráfico de barras.



  1. Definido un origen de datos del tipo MDX  y en concreto MDX over Mondrian JNDI 
    1. El nombre del origen de datos que vamos a utilizar es Posicion_DS
    2. El origen de datos es sobre el schema SampleData que usa el JNDI SampleData
    3. La consulta que vamos a utilizar es una que nos permitirá ver el actual y el budget para todas y cada una de las posiciones:


      select NON EMPTY {[Measures].[Actual], [Measures].[Budget]} ON COLUMNS,
        NON EMPTY {[Positions].[All Positions].Children} ON ROWS
      from [Quadrant Analysis]



  2. Definimos un componente que utiliza ese origen de datos:
    1. El componente es un chart
    2. Concretamente es un CCC Dot Chart
    3. Definimos un alto y un ancho para el gráfico.
    4. Definimos el origen de datos (datasource) de ese gráfico como el que acabamos de definir  Posicion_DS 
    5. Le decimos que viene de una crosstab
    6. Definimos el objeto html ( HtmlObject ) donde ubicaremos nuestro gráfico. El contenedor que hemos preparado en la plantilla de visualización
    7. Finalmente, en las propiedades avanzadas ( AdvancedProperties ) definimos que la orientación es horizontal para que se vea un poco mejor y ampliamos el tamaño que tendrá el eje de las Y (  YY axis size ) para que los nombres puedan caber 




Finalmente vamos a poner el primero de los tacómetros. Los tacómetros son un tipo de gráfico especial porque:
  • Es de los que mas le gusta a los usuarios finales. A todo el mundo le gusta la velocidad.
  • Es un gráfico aparentemente sencillo pero que encierra la complejidad interna que supone presentar su información carácteristica:
    • Rango malo
    • Rango medio
    • Rango bueno
    • Valor máximo
    • Valor obtenido.
  • No hay un componente (al menos yo no lo conozco) CCC que nos proporcione este tipo de gráfico por lo que tendremos que utilizar una xaction. Esto además nos permitirá ver como interactuar con las xactions
Es por esto que los tacómetros que vamos a utilizar son fruto de una xaction que invocaremos.  La xaction que voy a utilizar es esta y la ubicaré bajo la ruta de soporte xactions. En futuros post entraré en detalle sobre este punto ya que no quiero irme del tema.






No voy a poner el resto de los tacómetros porque este post empieza a ser largo y tampoco es necesario repetir pasos. Vamos ya a  la última parte interesante. La interacción del usuario.

Dotar el cuadro de interacción y vincular elementos 


Ahora es cuando viene la grácia de los cuadros de mandos. Es cuando vamos a dotar a nuestro cuadro de interacción. Vamos a dotarlo de la capacidad de responder a preguntas.

Para nuestro cuadro, lo que vamos a hacer es habilitar la posibilidad de poder hacer click en cualquiera de las barras de la gráfica de departamento y que nos permita ver el desglose de ese departamento en función de las diferentes posiciones.

Para explicar el funcionamiento voy a valerme de la siguiente gráfica:

Partimos de la base que el usuario quiere poder filtrar la información. Es decir, el usuario quiere poder clicar en alguno de los departamentos y ver la información relativa a ese departamento. A tal efecto definiremos una serie de parámetros para registrar todos esos filtros que queremos definir.  A su vez los componentes de nuestro cuadro de mandos pueden afectar a dichos parámetros. Igualmente  los componentes de nuestro cuadro de mandos pueden escuchar a dichos parámetros y reaccionar a un cambio.

Partiendo de esta arquitectura cuando un usuario clica en una de las gráficas lo que  acontecerán  es:

  1.  El usuario clicará en una de las barras del gráfico de departamentos.  Este click establecerá un nuevo valor en el parámetro Parámetro_Departamento que hemos definido a tal efecto.
  2. El gráfico de posiciones (cargos) escucha al parámetro Parámetro_Departamento de forma que cuando se establece un nuevo valor para el sábe que tiene que re-calcularse.
  3. Para re-calcularse toma el valor del parámetro Parámetro_Departamento
  4. Con el valor del parámetro  Parámetro_Departamento  invoca la consulta que lo nutre de valores proporcionándoselo para que lo utilize.
  5. La consulta se ejecuta tomando el valor del parámetro Parámetro_Departamento  y devuelve los resultados.
Lo que va a pasar pues, es que al clicar en una de las barras estableceremos un nuevo valor en el parámetro Parámetro_Departamento. Como que el gráfico de puntos sabe que tiene que reaccionar a los cambios de este parámetro, este se recalculará y utilizará para ello el  Parámetro_Departamento  en su consulta.


Todo esto para que, para el usuario lo que aparentemente pasará será esto:

Que hago click en un departamento y el gráfico de posiciones se recalcula mostrándome sólo los valores para ese departamento.



En resumeno, que hemos hecho?

  1. Hemos definido el parámetro Parametro_Departamento para manejar el departamento que queremos ver. El parámetro lo hemos inicializado con "Children" que es la palabra reservada que cuando la ponga en la consulta me dará todos los departamentos.
  2. Le hemos dicho a la gráfica Graf_Departamento que es clicable y le hemos proporcionado la función que ejecutará cuando se realize un click:



    function(a,b,c){
    if(b=="All Departments"){
        mi_var= "Children";
        }else{
        mi_var = "[" + b + "]";
        }
     Dashboards.fireChange('Parametro_Departamento',mi_var);
    }

  3. Le hemos dicho al gráfico Graf_Posicion que debe escuchar al parámetro Parametro_Departamento. Igualmente le hemos dicho que para recalcularse tomará en cuenta el parámetro Parametro_Departamento.
  4. Finalmente, en la consulta Posicion_ds que es la consulta que llena de datos el gráfico  Graf_Posicion se le ha dicho que espera un parámetro que se llamará Parametro_Departamento y se ha vuelto a inicializar a Children para que la carga inicial relativa a todos los departamentos devuelva todos.

Y... Listo!. Ya tenemos la funcionalidad básica de nuestro cuadro de mandos. Tan sólo nos falta vincular el tacómetro  y que responde a una xaction que hemos definido nosotros. Vamos a hacerlo....



Lo que hemos hecho es lo mismo  una vez mas... Decirle que escuche al parámetro Parametro_Departamento  y pasarle los parámetros que espera recibir la xaction.  La xaction que hemos diseñado para que pinte el tacómetro espera 3 parámetros:
  • Posicion: Es una xaction genérica que espera que le pases como parámetro si quieres que te muestre el primero, el segundo o el terceo.
  • Arriba_abajo: Si quieres que te enseñe el que mas o el que menos. El que está por arriba (TopCount) o el que está por debajo (BottomCount)
  • Departamento: Pues eso, si se refiere a un departamento específico o a cualquiera.


Ahora ya sí que está toda la funcionalidad  básica. A partir de aquí es acabar de pintar el resto de tacómetros y vincularlos.

Si bien es cierto que quedan muchas cosas que hacer,  a estas alturas yo ya se lo enseñaría al usuario final para que tuviera una idea de su aspecto y funcionalidades.



Si te ha gustado este tutorial te recomiendo mucho  este post de Slawomir Chodnicki donde se entra en funcionalidades en las que yo no he querido entrar para no repetirme pero que considero interesantes.

Si te interesa adquirir un conocimiento mas profundo... Bueno siempre es buena idea preguntarle al creador, Pedro Alves.

Si tienes cualquier duda sobre este tutorial, pues estaré encantado de saber que has estado leyendo hasta aqui. ¡Pregunta sin vergüenza!

Finalmente si quieres el ejemplo que hemos estado haciendo puedes descargarlo de aqui. Pon lo en pentaho-solutions y te debería funcionar. Espero que te sea útil.

18 comentarios:

  1. Gracias! Me alegra que te haya gustado!

    ResponderEliminar
  2. Juanjo. You are the man. Great post. Keep up the good job.

    ResponderEliminar
  3. Exelente Gracias
    pero tengo una duda y si indicador es mayor a 200 que es el limite del velocímetro como le hago para aumentarlo??

    Saludos vgv

    ResponderEliminar
  4. El post es muy interesante. Lastima que en la calidad de los videos no se llega a apreciar los parametros que setea

    ResponderEliminar
  5. Excelente post... fue de mucha ayuda...Gracias

    ResponderEliminar
  6. Excelente, pero tengo un problemilla, cuando quiero seleccionar el Schema no se ven los esquemas disponibles, a que se debe? falta alguna configuración? Estoy usando Pentano 3.9 y el CDE-bundle-1.0-RC3.tar. Gracias anticipadas por tu respuesta

    ResponderEliminar
    Respuestas
    1. es muy sencillo... cuando vayas a introducir le nombre... aprieta la tecla "flecha hacia abajo"

      Eliminar
  7. Los olap, en este dashboard para que los utilizas saludos.

    ResponderEliminar
  8. muy buen tutorial,... pero tienes mas informacion sobre el componente tabla, sobre todo en las propiedades...

    Saludos...

    ResponderEliminar
  9. Excelente post, muchas gracias, lo que no me queda claro es el uso del velocimetro, de donde tomas la imágen?

    Saludos

    ResponderEliminar
  10. Hola,

    Excelente post.

    Aunque en el caso de dotarlo de interactividad, en mi caso, con un ejemplo parecido no me funcionó con la función javascript que propones ya que solo me carga datos en un parámetro.

    Dejo aquí una solución:

    function(scene){
    Dashboards.fireChange('bug',scene.vars.category.value);
    }

    Esto lo que hace es sacar el campo category (en el caso del post "b") de un objeto

    Saludos

    ResponderEliminar
  11. Hola, excelente tutorial, me ha ayudado mucho, tengo duda en la última función javascript, tienes otra liga de donde pueda bajar el archivo? La liga que pones no funciona. Saludos!

    ResponderEliminar
  12. Hola Juanjo, Excelente tutorial. Solo tengo un problemilla, no alcanzo a distinguir la ultima linea de la modificacion del MDX.
    select NON EMPTY {[Measures].[Actual], [Measures].[Budget]} ON COLUMNS,
    NON EMPTY {[Positions].[All Positions].Children} ON ROWS
    from [Quadrant Analysis]

    entiendo que es algo como esto...
    where [Parametro_Departamento].[]

    pero como te repito no estoy seguro y no alcanzo a distinguir. si me podes indicar te lo agradeceria mucho.

    ResponderEliminar
  13. Hola Juanjo,

    Me gustaría saber si es posible crear parametros que se puedan pasar por session.

    Gracias

    ResponderEliminar
  14. hola, Excelente tutorial!
    no puedo descargar el zip del ejemplo "mi_primer_cdm.zip"
    cómo puedo hacerlo?
    Gracias

    ResponderEliminar