mx.edu.um.mateo.inventario.dao.impl.ProductoDaoHibernate.java Source code

Java tutorial

Introduction

Here is the source code for mx.edu.um.mateo.inventario.dao.impl.ProductoDaoHibernate.java

Source

/*
 * The MIT License
 *
 * Copyright 2012 Universidad de Montemorelos A. C.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package mx.edu.um.mateo.inventario.dao.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import mx.edu.um.mateo.general.dao.BaseDao;
import mx.edu.um.mateo.general.model.Imagen;
import mx.edu.um.mateo.general.model.Usuario;
import mx.edu.um.mateo.general.utils.Constantes;
import mx.edu.um.mateo.inventario.dao.ProductoDao;
import mx.edu.um.mateo.inventario.model.HistorialProducto;
import mx.edu.um.mateo.inventario.model.Producto;
import mx.edu.um.mateo.inventario.model.TipoProducto;
import mx.edu.um.mateo.inventario.model.XProducto;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author J. David Mendoza <jdmendoza@um.edu.mx>
 */
@Repository
@Transactional
public class ProductoDaoHibernate extends BaseDao implements ProductoDao {

    public ProductoDaoHibernate() {
        log.info("Nueva instancia de ProductoDao");
    }

    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> lista(Map<String, Object> params) {
        log.debug("Buscando lista de productos con params {}", params);
        if (params == null) {
            params = new HashMap<>();
        }

        if (!params.containsKey("max")) {
            params.put("max", 10);
        } else {
            params.put("max", Math.min((Integer) params.get("max"), 100));
        }

        if (params.containsKey("pagina")) {
            Long pagina = (Long) params.get("pagina");
            Long offset = (pagina - 1) * (Integer) params.get("max");
            params.put("offset", offset.intValue());
        }

        if (!params.containsKey("offset")) {
            params.put("offset", 0);
        }
        Criteria criteria = currentSession().createCriteria(Producto.class);
        Criteria countCriteria = currentSession().createCriteria(Producto.class);

        if (params.containsKey("almacen")) {
            criteria.createCriteria("almacen").add(Restrictions.idEq(params.get("almacen")));
            countCriteria.createCriteria("almacen").add(Restrictions.idEq(params.get("almacen")));
        }

        if (params.containsKey("inactivo")) {
            criteria.add(Restrictions.eq("inactivo", true));
            countCriteria.add(Restrictions.eq("inactivo", true));
        } else {
            Disjunction propiedades = Restrictions.disjunction();
            propiedades.add(Restrictions.eq("inactivo", Boolean.FALSE));
            propiedades.add(Restrictions.isNull("inactivo"));
            criteria.add(propiedades);
            countCriteria.add(propiedades);
        }

        if (params.containsKey("filtro")) {
            String filtro = (String) params.get("filtro");
            Disjunction propiedades = Restrictions.disjunction();
            propiedades.add(Restrictions.ilike("sku", filtro, MatchMode.ANYWHERE));
            propiedades.add(Restrictions.ilike("nombre", filtro, MatchMode.ANYWHERE));
            propiedades.add(Restrictions.ilike("descripcion", filtro, MatchMode.ANYWHERE));
            propiedades.add(Restrictions.ilike("marca", filtro, MatchMode.ANYWHERE));
            propiedades.add(Restrictions.ilike("modelo", filtro, MatchMode.ANYWHERE));
            propiedades.add(Restrictions.ilike("ubicacion", filtro, MatchMode.ANYWHERE));
            criteria.add(propiedades);
            countCriteria.add(propiedades);
        }

        if (params.containsKey("order")) {
            String campo = (String) params.get("order");
            if (params.get("sort").equals("desc")) {
                criteria.addOrder(Order.desc(campo));
            } else {
                criteria.addOrder(Order.asc(campo));
            }
        }

        if (!params.containsKey("reporte")) {
            criteria.setFirstResult((Integer) params.get("offset"));
            criteria.setMaxResults((Integer) params.get("max"));
        }
        params.put("productos", criteria.list());

        countCriteria.setProjection(Projections.rowCount());
        params.put("cantidad", (Long) countCriteria.list().get(0));

        return params;
    }

    @SuppressWarnings("unchecked")
    @Override
    @Transactional(readOnly = true)
    public List<Producto> listaParaSalida(String filtro, Long almacenId) {
        Criteria criteria = currentSession().createCriteria(Producto.class);
        criteria.createCriteria("almacen").add(Restrictions.idEq(almacenId));
        filtro = "%" + filtro + "%";
        Disjunction propiedades = Restrictions.disjunction();
        propiedades.add(Restrictions.ilike("sku", filtro, MatchMode.ANYWHERE));
        propiedades.add(Restrictions.ilike("nombre", filtro, MatchMode.ANYWHERE));
        propiedades.add(Restrictions.ilike("descripcion", filtro, MatchMode.ANYWHERE));
        propiedades.add(Restrictions.ilike("marca", filtro, MatchMode.ANYWHERE));
        propiedades.add(Restrictions.ilike("modelo", filtro, MatchMode.ANYWHERE));
        propiedades.add(Restrictions.ilike("ubicacion", filtro, MatchMode.ANYWHERE));
        criteria.add(propiedades);

        propiedades = Restrictions.disjunction();
        propiedades.add(Restrictions.eq("inactivo", Boolean.FALSE));
        propiedades.add(Restrictions.isNull("inactivo"));
        criteria.add(propiedades);

        criteria.add(Restrictions.gt("existencia", BigDecimal.ZERO));
        criteria.setMaxResults(10);
        return criteria.list();
    }

    @Override
    @Transactional(readOnly = true)
    public Producto obtiene(Long id) {
        return (Producto) currentSession().get(Producto.class, id);
    }

    @Override
    public Producto crea(Producto producto, Usuario usuario) {
        Session session = currentSession();
        if (usuario != null) {
            producto.setAlmacen(usuario.getAlmacen());
        }
        producto.setTipoProducto(
                (TipoProducto) session.get(TipoProducto.class, producto.getTipoProducto().getId()));
        Date fecha = new Date();
        producto.setFechaCreacion(fecha);
        producto.setFechaModificacion(fecha);
        session.save(producto);
        audita(producto, usuario, Constantes.CREAR, fecha);
        session.flush();
        return producto;
    }

    @Override
    public Producto crea(Producto producto) {
        return this.crea(producto, null);
    }

    @Override
    public Producto actualiza(Producto producto) {
        return this.actualiza(producto, null);
    }

    @Override
    public Producto actualiza(Producto otro, Usuario usuario) {
        Date fecha = new Date();
        Session session = currentSession();
        Producto producto = (Producto) session.get(Producto.class, otro.getId());
        BeanUtils.copyProperties(otro, producto,
                new String[] { "id", "version", "precioUnitario", "ultimoPrecio", "existencia", "puntoReorden",
                        "tipoProducto", "almacen", "imagenes", "fechaCreacion", "fechaInactivo", "inactivo" });
        producto.setTipoProducto((TipoProducto) session.get(TipoProducto.class, otro.getTipoProducto().getId()));
        if (otro.getInactivo() && (producto.getInactivo() == null || !producto.getInactivo())) {
            producto.setInactivo(true);
            producto.setFechaInactivo(fecha);
        } else if (!otro.getInactivo() && producto.getInactivo() != null && producto.getInactivo()) {
            producto.setInactivo(false);
            producto.setFechaInactivo(null);
        }
        producto.setFechaModificacion(fecha);
        if (producto.getImagenes().size() > 0) {
            Imagen imagen = producto.getImagenes().get(0);
            producto.getImagenes().clear();
            producto.getImagenes().add(otro.getImagenes().get(0));
            session.delete(imagen);
            session.flush();

        } else if (otro.getImagenes() != null && otro.getImagenes().size() > 0) {
            producto.getImagenes().add(otro.getImagenes().get(0));
        }
        session.update(producto);
        audita(producto, usuario, Constantes.ACTUALIZAR, fecha);
        session.flush();
        return producto;
    }

    @Override
    public String elimina(Long id) {
        return elimina(id, null);
    }

    @Override
    public String elimina(Long id, Usuario usuario) {
        Producto producto = obtiene(id);
        String nombre = producto.getNombre();
        audita(producto, usuario, Constantes.ELIMINAR, new Date());

        currentSession().delete(producto);
        currentSession().flush();
        return nombre;
    }

    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> historial(Long id, Map<String, Object> params) {
        StringBuilder sb = new StringBuilder();
        sb.append("select new map(");
        sb.append("p.actividad as actividad, p.creador as creador ");
        sb.append(", p.precioUnitario as precioUnitario, p.ultimoPrecio as ultimoPrecio ");
        sb.append(", p.existencia as existencia ");
        sb.append(", p.fechaCreacion as fecha ");
        sb.append(", p.entradaId as entradaId ");
        sb.append(", p.salidaId as salidaId ");
        sb.append(", p.cancelacionId as cancelacionId ");
        sb.append(", (select e.folio from Entrada e where e.id = p.entradaId) as folioEntrada ");
        sb.append(", (select s.folio from Salida s where s.id = p.salidaId) as folioSalida ");
        sb.append(", (select c.folio from Cancelacion c where c.id = p.cancelacionId) as folioCancelacion ");
        sb.append(") from XProducto p where p.productoId = :productoId order by p.id desc");
        Query query = currentSession().createQuery(sb.toString());
        query.setLong("productoId", id);
        if (params.containsKey("max")) {
            Integer max = (Integer) params.get("max");
            query.setMaxResults(max);
            params.put("max", max);
        } else {
            query.setMaxResults(10);
            params.put("max", 10);
        }

        if (params.containsKey("pagina")) {
            Long pagina = (Long) params.get("pagina");
            Long offset = (pagina - 1) * (Integer) params.get("max");
            params.put("offset", offset.intValue());
        }

        if (params.containsKey("offset")) {
            Integer offset = (Integer) params.get("offset");
            query.setFirstResult(offset);
            params.put("offset", offset);
        } else {
            query.setFirstResult(0);
            params.put("offset", 0);
        }
        params.put("historial", query.list());

        sb = new StringBuilder();
        sb.append("select count(*) as cantidad from XProducto p where p.productoId = :productoId");
        query = currentSession().createQuery(sb.toString());
        query.setLong("productoId", id);
        params.put("cantidad", query.uniqueResult());

        return params;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void guardaHistorial(Date fecha) {
        log.debug("Buscando historial de productos de la fecha {}", fecha);
        StringBuilder sb = new StringBuilder();
        sb.append("select new HistorialProducto(p.id, p.almacen) from Producto p order by p.codigo");
        log.debug("Cargando lista de productos");
        List<HistorialProducto> productos = currentSession().createQuery(sb.toString()).list();
        List<HistorialProducto> resultado = new ArrayList<>();
        log.debug("Buscando historial por producto ({})", productos.size());
        int cont = 0;
        for (HistorialProducto hp : productos) {
            if (cont++ % 10 == 0) {
                log.debug("Leyendo {} / {} Productos", cont, productos.size());
            }
            sb = new StringBuilder();
            sb.append(
                    "select new map(p.existencia as existencia) from XProducto p where p.productoId = :productoId and p.fechaCreacion <= :fecha order by p.fechaCreacion desc");
            Query query = currentSession().createQuery(sb.toString());
            query.setLong("productoId", hp.getProductoId());
            query.setTimestamp("fecha", fecha);
            query.setMaxResults(1);
            Map<String, Object> existencia = (Map<String, Object>) query.uniqueResult();
            if (existencia != null && !existencia.isEmpty()) {
                sb = new StringBuilder();
                sb.append("select hp from HistorialProducto hp where fecha = :fecha and productoId = :productoId");
                Query query2 = currentSession().createQuery(sb.toString());
                query2.setDate("fecha", fecha);
                query2.setLong("productoId", hp.getProductoId());
                HistorialProducto otro = (HistorialProducto) query2.uniqueResult();
                if (otro != null) {
                    hp = otro;
                }
                hp.setExistencia((BigDecimal) existencia.get("existencia"));
                hp.setFecha(fecha);
                resultado.add(hp);
            }
        }
        log.debug("{} / {} Productos", cont, productos.size());
        log.debug("Guardando historial de productos ({})", resultado.size());
        cont = 0;
        for (HistorialProducto hp : resultado) {
            if (cont++ % 10 == 0) {
                log.debug("Guardando {} / {} Productos", cont, resultado.size());
            }
            currentSession().saveOrUpdate(hp);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> obtieneHistorial(Map<String, Object> params) {
        List<Producto> resultado = new ArrayList<>();
        if (params.containsKey("fecha") && params.containsKey("almacen")) {
            Date fecha = (Date) params.get("fecha");
            Long almacenId = (Long) params.get("almacen");
            log.debug("Buscando historial de productos de la fecha {}", fecha);
            StringBuilder sb = new StringBuilder();
            sb.append(
                    "select new HistorialProducto(p.id, p.almacen) from Producto p where p.almacen.id = :almacenId order by p.codigo");
            log.debug("Cargando lista de productos");
            Query query1 = currentSession().createQuery(sb.toString());
            query1.setLong("almacenId", almacenId);
            List<HistorialProducto> productos = query1.list();
            log.debug("Buscando historial por producto ({})", productos.size());
            int cont = 0;
            for (HistorialProducto hp : productos) {
                if (cont++ % 10 == 0) {
                    log.debug("Leyendo {} / {} Productos", cont, productos.size());
                }
                sb = new StringBuilder();
                sb.append(
                        "select new Producto(p.productoId, p.sku, p.nombre, p.descripcion, p.marca, p.modelo, p.ubicacion, p.existencia, p.unidadMedida, p.precioUnitario, p.fraccion, tp.nombre, a.nombre) from XProducto p, TipoProducto tp, Almacen a where p.tipoProductoId = tp.id and p.almacenId = a.id and p.productoId = :productoId and p.fechaCreacion <= :fecha order by p.fechaCreacion desc");
                Query query = currentSession().createQuery(sb.toString());
                query.setLong("productoId", hp.getProductoId());
                query.setTimestamp("fecha", fecha);
                query.setMaxResults(1);
                Producto producto = (Producto) query.uniqueResult();
                if (producto != null) {
                    resultado.add(producto);
                }
            }
            log.debug("{} / {} Productos", cont, productos.size());
            log.debug("Se encontro el historial de productos ({})", resultado.size());

            params.put("productos", resultado);
            params.put("cantidad", 1L);
            params.put("max", 1);
        }
        return params;
    }

    @Override
    public Map<String, Object> historialTodos(Map<String, Object> params) {

        return params;
    }

    private void audita(Producto producto, Usuario usuario, String actividad, Date fecha) {
        XProducto xproducto = new XProducto();
        BeanUtils.copyProperties(producto, xproducto, new String[] { "id", "version" });
        xproducto.setProductoId(producto.getId());
        xproducto.setTipoProductoId(producto.getTipoProducto().getId());
        xproducto.setAlmacenId(producto.getAlmacen().getId());
        xproducto.setFechaCreacion(fecha);
        xproducto.setActividad(actividad);
        xproducto.setCreador((usuario != null) ? usuario.getUsername() : "sistema");
        currentSession().save(xproducto);
    }

    @SuppressWarnings("unchecked")
    @Override
    public void arreglaDescripciones() {
        log.debug("Arreglando descripciones");
        Date fecha = new Date();
        Query query = currentSession().createQuery("from Producto");
        List<Producto> productos = query.list();
        int cont = 0;
        for (Producto producto : productos) {
            if (StringUtils.isBlank(producto.getDescripcion())) {
                log.debug("Actualizando {}", producto);
                producto.setDescripcion(producto.getNombre());
                currentSession().update(producto);
                this.audita(producto, null, Constantes.ACTUALIZAR, fecha);
                cont++;
            }
        }
        currentSession().flush();
        log.debug("Se arreglaron {} de {}", cont, productos.size());
    }

    @Override
    public String eliminaImagen(Long productoId, Usuario usuario) {
        log.debug("Elimina imagenes de producto {}", productoId);
        Producto producto = (Producto) currentSession().get(Producto.class, productoId);
        String nombre = producto.getNombre();
        producto.getImagenes().clear();
        currentSession().update(producto);
        currentSession().flush();
        return nombre;
    }

    @Override
    public List<Map<String, Object>> revisaEntradas(String fechaString, Usuario usuario) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List<Map<String, Object>> entradas = new ArrayList<>();
        try {
            Date fecha = sdf.parse(fechaString);
            StringBuilder s = new StringBuilder();
            s.append(
                    "select new map(x.entradaId as entradaId, e.folio as folio, x.productoId as productoId, p.sku as sku, count(x.productoId) as cantidad) ");
            s.append("from XProducto x, Entrada e, Producto p ");
            s.append(
                    "where x.entradaId = e.id and x.productoId = p.id and x.fechaCreacion >= :fecha and x.almacenId = :almacenId ");
            s.append("group by x.entradaId, e.folio, x.productoId, p.sku ");
            s.append("order by cantidad desc, e.folio desc");
            Query query = currentSession().createQuery(s.toString());
            query.setDate("fecha", fecha);
            query.setLong("almacenId", usuario.getAlmacen().getId());
            List<Map<String, Object>> resultados = (List<Map<String, Object>>) query.list();
            for (Map<String, Object> resultado : resultados) {
                if (((Long) resultado.get("cantidad")) > 1) {
                    entradas.add(resultado);
                }
            }
        } catch (ParseException e) {
            log.error("No pude entender la fecha " + fechaString, e);
        }

        return entradas;
    }
}