Skip to main content

JmoordbUnit con filtros entre fechas en List embebidos

JmoordbUnit con filtros entre fechas en List<entity> embebidos

Las bases de datos NoSQL, tales como MongoDB nos permiten gran flexibilidad comparados con bases de datos relacionales.





Por ejemplo en una base de datos de facturación de un sistema relacional, tendríamos una tabla de facturas y otra de Pagare, con cientos de registros asociados.

Mediante SQL podemos hacer consultas, en el ejemplo, buscamos en la tabla de pagare todas aquellas facturas con un estatus especifico y con la condición que estos pagares estén entre una fecha de inicio y de fin y que tengan el estatus de cancelado="no".
Usamos un select o un join, en el cual iteramos la consulta sobre dos tablas para obtener los resultados.


Ahora lo vemos desde una perspectiva NoQSL, en el cual podemos almacenar dentro de la colección Factura una lista embebida de Pagare. De manera que al consultar en la colección Factura, automáticamente tendremos acceso a los pagares que se almacenan en la misma colección.




Esquema del Json de Factura

  • Utilizaremos ejbjmoord como APi para comunicarnos con MongoDB.
  • jmoordbUnit para generar los test progresivos (Nos permiten generar ademas del test, una interfaz gráfica con las pruebas).
Pasos:
Creamos dos proyectos en NetBeans IDE
Un proyecto EJB Module llamado storejb


y otro proyecto de tipo Payara Micro Application llamado storetest




Agregar la dependencia de jmoordbunit Dependencias
  <dependency>
            <groupId>com.github.avbravo</groupId>
            <artifactId>jmoordbunit</artifactId>
            <version>0.4.4</version>
        </dependency>

jmoordbUnit genera los archivos de reportes

Clase Factura:



Contiene una Lista embebida de Pagare.
    @Embedded
    List<Pagare> pagare;
 



MOSTRAR TODAS LOS PAGARES


Usamos UnitTest para generar la salida del test.

unitTest.form();
            unitTest.formTitle("Reporte de Todas las facturas con pagare");
            unitTest.panel();
             unitTest.panelAddTableHeader("Pagare", Arrays.asList(new RowView("idfactura"), new RowView("Pagare"), new RowView("Cancelado"),
                    new RowView("Fecha")));
            flist.forEach((f) -> {
                f.getPagare().forEach((p) -> {
                    unitTest.panelAddTableCol(Arrays.asList(new ColView(f.getIdfactura()), new ColView(p.getNumero()),
                            new ColView(p.getCancelado()),
                            new ColView(p.getFechavencimiento())
                    ));
                });

            });
            unitTest.panelAddTableClose();

            unitTest.panelClose();
            unitTest.formClose();

Podemos ver todos los pagares dentro de las facturas y las fechas de vencimiento y el valor de cancelado.


FILTRAR EL LIST<> EMBEBIDO.


Dibujamos las cajas de texto del filtro.
 List<Factura> listFactura = facturaRepository.filters(filter, new Document("idfactura", 1));
            unitTest.assertNotEquals(nameOfMethod(), 0, listFactura.size());

            unitTest.form();
            unitTest.formTitle("Filtro");
            unitTest.panel();

            unitTest.panelAddInputText(Arrays.asList(new InputText("desde", firstDate.toString()),
                    new InputText("hasta", lastDate.toString()), new InputText("cancelado", "no"))
            );

            unitTest.panelClose();
            unitTest.buttonGreen("Filtrar");
            unitTest.formClose();





Aplicamos el filtro generando un Filters para cada posición dentro del List<>

Filtramos cada elemento del List<> embebido indicando la posición dentro del List<>, por ejemplo pagare.0.cancelado, pagare.1.cancelado , y el filtro entre fechas. Utilizamos una función que denominamos functionFilter() que genera un solo Bson  que contiene los filtros para cada posición.

  Integer anio = 2019;
            Integer mes = 4;
            Date firstDate = DateUtil.primerDiaDelMesEnFecha(anio, mes);

            Date lastDate = DateUtil.getDateLastOfMonth(anio, mes);

            Bson filterfactura = Filters.and(Filters.eq("almacen.idalmacen", 6), Filters.or(Filters.eq("estatusfactura.idestatusfactura", 1), Filters.eq("estatusfactura.idestatusfactura", 2), Filters.eq("estatusfactura.idestatusfactura", 6), Filters.eq("estatusfactura.idestatusfactura", 7)));

            Bson filterpagare = functionFilter(0, firstDate,lastDate);
            for (int i = 1; i < 13; i++) {
                Bson f = functionFilter(i, firstDate,lastDate);
                filterpagare = Filters.or(filterpagare, f);
            }   


Bson filter = Filters.and(filterfactura, filterpagare);

Ejecutar el filtro


 List<Factura> listFactura = facturaRepository.filters(filter, new Document("idfactura", 1));


Función que genera el filtro para cada elemento                  


 private Bson functionFilter(Integer i, Date startDate, Date lastDate) {

        Bson filter = Filters.and(
                Filters.gte("pagare." + i + ".fechavencimiento", startDate),
                Filters.lte("pagare." + i + ".fechavencimiento", lastDate),
                Filters.eq("pagare." + i + ".cancelado", "no")
        );
        return filter;
    }


Se realiza el filtro correctamente, mostrando solo la factura 5.


Aplicar un filtro genérico sin indicar la posición dentro del List<>

Cuando usamos este filtro sin especificar la posición dentro del List<>. no funciona el and, se comporta como un or.

 Bson filterfactura = Filters.and(Filters.eq("almacen.idalmacen", 6), Filters.or(Filters.eq("estatusfactura.idestatusfactura", 1), Filters.eq("estatusfactura.idestatusfactura", 2), Filters.eq("estatusfactura.idestatusfactura", 6), Filters.eq("estatusfactura.idestatusfactura", 7)));

       
      
            Bson filterpagare = Filters.and(Filters.eq("pagare.cancelado", "no"),
                    Filters.gte("pagare.fechavencimiento", firstDate),
                    Filters.lte("pagare.fechavencimiento", lastDate)
            );
            Bson filter = Filters.and(filterfactura, filterpagare);


Observen que se genera un listado de todas las facturas que contengan un rango de fecha, pero ignora la condición cancelado = "no"
Aquí falla un filtro de ese tipo dentro de MongoDB, ya que el buscara en la lista cualquier pagare que tenga la condición entre fechas y cualquier pagare que tenga cancelado ="no", sin restringuir que sea el mismo pagare que se este buscando.
Recomendación:
  • Cuando desee hacer filtros dentro de un List<> embebido genere todas las posiciones del list para hacer el filtro.




Comments

Popular posts from this blog

Tutorial básico de aplicaciones Web con NetBeans parte 1

NetBeans ofrece un excelente soporte para el desarrollo de aplicaciones Web, en esta ocasión lo haremos utilizando el Framework Java Server Faces 2.0. En el Menu Seleccionamos Nuevo->Proyecto y luego en Categorias Java Web y en tipo de Proyectos Web  Application indicamos el nombre del proyecto Seleccinamos el servidor Web, usamos GlassFish ya que este soporta EJB3.0 y JSF 2.0 Framework Java Server Faces El IDE genera el esquelto del proyecto Web Pages   almacenamos las paginas .html, xhtml, jsf, los archivos de recursos, los scripts .js, imagenes Source Packages    Son las clases Java  Test Packages    Son las clases que usamos para los Test Libraries     Tenemos las bibliotecas de Java y GlassFish necesarias para ejecutar la aplicación Web. Test Libraries     Están las bibliotecas usadas para los test  Configuration Files    Archivos de configuración de la aplicación. Ejecutamos la...

Incrementar Memoria NetBeans

Algunas veces necesitamos incrementar la memoria para un mejor rendimiento. http://www.netbeans.org/community/releases/55/uml-download.html Este es un ejemplo para UML. Descripción en ingles. Increasing Memory Settings (applicable to all builds) The default memory settings for NetBeans should be increased for UML projects. If you have the available memory, Locate your NetBeans installation directory ($install_dir). This can be found by starting up NetBeans and selecting Help -> About then select the Detail tab. Edit the $install_dir/etc/netbeans.conf file. Find the line defining netbeans_default_options . Increase the maximum memory attribute to -J-Xmx512m. If you experience heap overflows while working with larger files, you should increase this value further.

Test con JUnit

El viernes dicte un taller en el que conversábamos sobre Tecnologías Java y luego desarrollamos una aplicación muy básica para demostrar como utilizar JUnit con NetBeans. Pasos: 1. Crear un proyecto Desktop con NetBeans 2. Crear una clase llamada Operaciones 3. Diseñados un formulario y agregramos componentes de manera que quede similar a la figura Código de los botones try { double a = Double.parseDouble(jTextField1.getText()); double b = Double.parseDouble(jTextField2.getText()); Operaciones operaciones = new Operaciones(); double r = operaciones.Sumar(a, b); jTextField3.setText(String.valueOf(r)); } catch (Exception ex) { JOptionPane.showMessageDialog(this, ex.getMessage().toString()); } 4. Creamos los test Seleccionamos las clases En el menu Herramientas,seleccionamos Crear pruebas JUnit Seleccionamos la versión de JUnit En la ventana siguiente seleccionamos los parámetros para nuestras pruebas . Le quitamos la selección a Probar Inicializador y Probar Finalizador NetBeans crea las...