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

JUnit con DataClassG

JUnit con DataClassG 0. ESQUEMA Services: Por cada beans crearemos una clase Services que se encargará de interactuar con el controller para realizar las operaciones de la base de datos. Se crearan los métodos insert, update,delete y los demas metodos para realizar las diversas operaciones. Test: Se crearán las clases para test de las clases Services. Form: Los formularios para la interactuar con el usuario. ProvinciasServices.java colocamos los métodos, insert, update,delete public class ProvinciasServices {    ProvinciasController provinciasController = new ProvinciasController();    public ProvinciasServices() {    }    public Boolean insert (Provincias provincias){        try{            if(provinciasController.insert(provincias)){              return tru...

Primefaces v13

 La versión nueva de primefaces v13.0 elimina el componente <p:repeat>  Consulte los cambios en  https://github.com/primefaces/primefaces/releases/tag/13.0.0 por lo tanto si necesita una solución similar considere utilizar  <p:carousel>  o  <ui:repeat> En la versión 13 genera una excepción