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

Libro JEE7 Capítulo 2. Crear aplicación Web

Capítulo 2. Crear  aplicación Web Modelo General Desarrollo de una aplicacion Web Dependencias Maven Usando el Asistente Maven del IDE Editar el archivo pom.xml MODELO DESARROLLO JPA Proceder a Crear los Entity con NetBeans Creación de los EJB CDI vs ManagedBeans CREAR UN CDI PARA EL MANEJO DE MENSAJES Código completo del CDI JSFUtil.java FACELETS CREAR PLANTILLA FACELETS CON <p:layout> de PRIMEFACES Código completo de template.xhtml Editar template.xhtml Crear la página Index.xhtml CREAR CDI BEANS ESTATUSCONTROLLER.java Crear los Facelets Template Client para insertar Estatus Editar el entity Estatus.java Editar EstatusFacade.java Convertidores Crear EstatusConverter.java Modelo General Desarrollo de una aplicacion Web Este capítulo  muestra el desarrollo de la aplicación de ejemplo de Scrum usando tecnologías JEE 7. Esta aplicación  permitirá insertar registros en una tabla utilizando JPA, primefaces / JavaServer Faces, EJB, CDI. P

Cambiando el estado de un checkbox

Cambiando el Estado de un CheckBox Algunas veces deseamos controlar el estado de un checkbox o cambiarlo segùn determinadas condiciones. Pasos: 1. Creamos un proyecto Web. 2. En el diseñador agregamos un checkbox y dos botones. * Dar click derecho en el checkbox y luego seleccionar Add Binding Attribute, para agregar los atributos al checkbox, de manera que los podamos usar en nuestro código. Generando automáticamente private Checkbox checkbox1 = new Checkbox(); public Checkbox getCheckbox1() { return checkbox1; } public void setCheckbox1(Checkbox c) { this.checkbox1 = c; } 3.Damos click derecho en el botón Habilitar, y seleccionamos Edit Action Event Handler. A continuación, agregamos el código: this.checkbox1.setSelected(true);, el método setSelected con valor true, marca el checkbox como seleccionado, y un valor de false, quita la marca. public String button1_action() { // TODO: Process the action. Return value is a navigation

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 aplicación  Esperamos que se inicie GlassFish y se cargue la aplicación Este se