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

Java tutorial

Introduction

Here is the source code for mx.edu.um.mateo.inventario.dao.impl.FacturaAlmacenDaoHibernate.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.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import mx.edu.um.mateo.general.dao.BaseDao;
import mx.edu.um.mateo.general.model.Usuario;
import mx.edu.um.mateo.general.utils.Constantes;
import mx.edu.um.mateo.inventario.dao.FacturaAlmacenDao;
import mx.edu.um.mateo.inventario.model.Almacen;
import mx.edu.um.mateo.inventario.model.Entrada;
import mx.edu.um.mateo.inventario.model.Estatus;
import mx.edu.um.mateo.inventario.model.FacturaAlmacen;
import mx.edu.um.mateo.inventario.model.Folio;
import mx.edu.um.mateo.inventario.model.Salida;
import mx.edu.um.mateo.inventario.model.XEntrada;
import mx.edu.um.mateo.inventario.model.XFacturaAlmacen;
import mx.edu.um.mateo.inventario.model.XSalida;
import mx.edu.um.mateo.inventario.utils.NoEstaAbiertaException;
import mx.edu.um.mateo.inventario.utils.NoEstaCerradaException;
import mx.edu.um.mateo.inventario.utils.NoSePuedeCancelarException;
import mx.edu.um.mateo.inventario.utils.NoSePuedeCerrarEnCeroException;
import mx.edu.um.mateo.inventario.utils.NoSePuedeCerrarException;
import org.hibernate.Criteria;
import org.hibernate.LockOptions;
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 FacturaAlmacenDaoHibernate extends BaseDao implements FacturaAlmacenDao {

    public FacturaAlmacenDaoHibernate() {
        log.info("Nueva instancia de FacturaAlmacenDao");
    }

    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> lista(Map<String, Object> params) {
        log.debug("Buscando lista de facturas 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(FacturaAlmacen.class);
        Criteria countCriteria = currentSession().createCriteria(FacturaAlmacen.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("fechaIniciado")) {
            log.debug("Buscando desde {}", params.get("fechaIniciado"));
            criteria.add(Restrictions.ge("fechaCreacion", params.get("fechaIniciado")));
            countCriteria.add(Restrictions.ge("fechaCreacion", params.get("fechaIniciado")));
        } else {
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 1);
            log.debug("Asignando busqueda desde {}", calendar.getTime());
            criteria.add(Restrictions.ge("fechaCreacion", calendar.getTime()));
            countCriteria.add(Restrictions.ge("fechaCreacion", calendar.getTime()));
        }

        if (params.containsKey("fechaTerminado")) {
            log.debug("Buscando hasta {}", params.get("fechaTerminado"));
            criteria.add(Restrictions.le("fechaCreacion", params.get("fechaTerminado")));
            countCriteria.add(Restrictions.le("fechaCreacion", params.get("fechaTerminado")));
        }

        if (params.containsKey("filtro")) {
            String filtro = (String) params.get("filtro");
            Disjunction propiedades = Restrictions.disjunction();
            propiedades.add(Restrictions.ilike("folio", 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));
            }
        } else {
            criteria.createCriteria("estatus").addOrder(Order.asc("prioridad"));
        }
        criteria.addOrder(Order.desc("fechaModificacion"));

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

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

        return params;
    }

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

    @Override
    @Transactional(readOnly = true)
    public FacturaAlmacen carga(Long id) {
        return (FacturaAlmacen) currentSession().load(FacturaAlmacen.class, id);
    }

    @Override
    public FacturaAlmacen crea(FacturaAlmacen factura, Usuario usuario) {
        Session session = currentSession();
        if (usuario != null) {
            factura.setAlmacen(usuario.getAlmacen());
        }
        Query query = currentSession().createQuery("select e from Estatus e where e.nombre = :nombre");
        query.setString("nombre", Constantes.ABIERTA);
        Estatus estatus = (Estatus) query.uniqueResult();
        factura.setEstatus(estatus);
        factura.setFolio(getFolioTemporal(factura.getAlmacen()));
        Date fecha = new Date();
        factura.setFechaCreacion(fecha);
        factura.setFechaModificacion(fecha);
        session.save(factura);

        audita(factura, usuario, Constantes.CREAR, fecha);

        session.flush();
        return factura;
    }

    @Override
    public FacturaAlmacen crea(FacturaAlmacen factura) {
        return this.crea(factura, null);
    }

    @Override
    @Transactional(rollbackFor = { NoEstaAbiertaException.class })
    public FacturaAlmacen actualiza(FacturaAlmacen factura) throws NoEstaAbiertaException {
        return this.actualiza(factura, null);
    }

    @Override
    @Transactional(rollbackFor = { NoEstaAbiertaException.class })
    public FacturaAlmacen actualiza(FacturaAlmacen otraFactura, Usuario usuario) throws NoEstaAbiertaException {
        FacturaAlmacen factura = (FacturaAlmacen) currentSession().get(FacturaAlmacen.class, otraFactura.getId());
        switch (factura.getEstatus().getNombre()) {
        case Constantes.ABIERTA:
            Session session = currentSession();
            factura.setVersion(otraFactura.getVersion());
            factura.setFecha(otraFactura.getFecha());
            factura.setComentarios(otraFactura.getComentarios());
            factura.setIva(otraFactura.getIva());
            factura.setTotal(otraFactura.getTotal());
            factura.setCliente(otraFactura.getCliente());
            Date fecha = new Date();
            factura.setFechaModificacion(fecha);
            session.update(factura);

            audita(factura, usuario, Constantes.ACTUALIZAR, fecha);

            session.flush();
            return factura;
        default:
            throw new NoEstaAbiertaException("No se puede actualizar una factura que no este abierta");
        }
    }

    @Override
    @Transactional(rollbackFor = { NoEstaAbiertaException.class, NoSePuedeCerrarException.class,
            NoSePuedeCerrarEnCeroException.class })
    public String cierra(Long facturaId, Usuario usuario)
            throws NoSePuedeCerrarException, NoSePuedeCerrarEnCeroException, NoEstaAbiertaException {
        FacturaAlmacen factura = (FacturaAlmacen) currentSession().get(FacturaAlmacen.class, facturaId);
        factura = cierra(factura, usuario);
        return factura.getFolio();
    }

    @Override
    @Transactional(rollbackFor = { NoEstaAbiertaException.class, NoSePuedeCerrarException.class,
            NoSePuedeCerrarEnCeroException.class })
    public FacturaAlmacen cierra(FacturaAlmacen factura, Usuario usuario)
            throws NoSePuedeCerrarException, NoSePuedeCerrarEnCeroException, NoEstaAbiertaException {
        if (factura != null) {
            if (factura.getEstatus().getNombre().equals(Constantes.ABIERTA)) {
                if (usuario != null) {
                    factura.setAlmacen(usuario.getAlmacen());
                }

                Date fecha = new Date();
                factura.setIva(BigDecimal.ZERO);
                factura.setTotal(BigDecimal.ZERO);
                Query query = currentSession().createQuery("select e from Estatus e where e.nombre = :nombre");
                query.setString("nombre", Constantes.FACTURADA);
                Estatus facturada = (Estatus) query.uniqueResult();
                for (Salida salida : factura.getSalidas()) {
                    salida.setEstatus(facturada);
                    salida.setFechaModificacion(fecha);
                    currentSession().update(salida);
                    audita(salida, usuario, Constantes.FACTURADA, fecha);
                    factura.setIva(factura.getIva().add(salida.getIva()));
                    factura.setTotal(factura.getTotal().add(salida.getTotal()));
                }

                for (Entrada entrada : factura.getEntradas()) {
                    entrada.setEstatus(facturada);
                    entrada.setFechaModificacion(fecha);
                    currentSession().update(entrada);
                    audita(entrada, usuario, Constantes.FACTURADA, fecha);
                    factura.setIva(factura.getIva().subtract(entrada.getIva()));
                    factura.setTotal(factura.getTotal().subtract(entrada.getTotal()));
                }

                query.setString("nombre", Constantes.CERRADA);
                Estatus estatus = (Estatus) query.uniqueResult();
                factura.setEstatus(estatus);
                factura.setFolio(getFolio(factura.getAlmacen()));
                factura.setFechaModificacion(fecha);

                currentSession().update(factura);

                audita(factura, usuario, Constantes.ACTUALIZAR, fecha);

                currentSession().flush();
                return factura;
            } else {
                throw new NoEstaAbiertaException("No se puede actualizar una factura que no este abierta");
            }
        } else {
            throw new NoSePuedeCerrarException("No se puede cerrar la factura pues no existe");
        }
    }

    @Override
    @Transactional(rollbackFor = { NoSePuedeCancelarException.class, NoEstaCerradaException.class })
    public FacturaAlmacen cancelar(Long id, Usuario usuario)
            throws NoEstaCerradaException, NoSePuedeCancelarException {
        FacturaAlmacen factura = (FacturaAlmacen) currentSession().get(FacturaAlmacen.class, id);
        if (factura != null) {
            if (factura.getEstatus().getNombre().equals(Constantes.CERRADA)) {
                Query query = currentSession().createQuery("select e from Estatus e where e.nombre = :nombre");
                query.setString("nombre", Constantes.CERRADA);
                Estatus cerrada = (Estatus) query.uniqueResult();

                Date fecha = new Date();
                for (Entrada entrada : factura.getEntradas()) {
                    entrada.setEstatus(cerrada);
                    entrada.setFechaModificacion(fecha);
                    currentSession().update(entrada);

                    audita(entrada, usuario, Constantes.ACTUALIZAR, fecha);
                }

                for (Salida salida : factura.getSalidas()) {
                    salida.setEstatus(cerrada);
                    salida.setFechaModificacion(fecha);
                    currentSession().update(salida);

                    audita(salida, usuario, Constantes.ACTUALIZAR, fecha);
                }

                query.setString("nombre", Constantes.CANCELADA);
                Estatus cancelada = (Estatus) query.uniqueResult();
                factura.setFechaModificacion(new Date());
                factura.setEstatus(cancelada);
                currentSession().update(factura);
                currentSession().flush();
                return factura;
            } else {
                throw new NoEstaCerradaException("No se puede actualizar una factura que no este cerrada", factura);
            }
        } else {
            throw new NoSePuedeCancelarException("No se puede cancelar la factura porque no existe", factura);
        }
    }

    @Override
    @Transactional(rollbackFor = { NoEstaAbiertaException.class })
    public String elimina(Long id) throws NoEstaAbiertaException {
        return this.elimina(id, null);
    }

    @Override
    @Transactional(rollbackFor = { NoEstaAbiertaException.class })
    public String elimina(Long id, Usuario usuario) throws NoEstaAbiertaException {
        FacturaAlmacen factura = obtiene(id);
        if (factura.getEstatus().getNombre().equals(Constantes.ABIERTA)) {
            String nombre = factura.getFolio();
            currentSession().delete(factura);
            audita(factura, usuario, Constantes.ELIMINAR, new Date());

            currentSession().flush();
            return nombre;
        } else {
            throw new NoEstaAbiertaException("No se puede eliminar una factura que no este abierta");
        }
    }

    private String getFolioTemporal(Almacen almacen) {
        Query query = currentSession()
                .createQuery("select f from Folio f where f.nombre = :nombre and f.almacen.id = :almacenId");
        query.setString("nombre", "FACTURA-TEMPORAL");
        query.setLong("almacenId", almacen.getId());
        query.setLockOptions(LockOptions.UPGRADE);
        Folio folio = (Folio) query.uniqueResult();
        if (folio == null) {
            folio = new Folio("FACTURA-TEMPORAL");
            folio.setAlmacen(almacen);
            currentSession().save(folio);
            currentSession().flush();
            return getFolioTemporal(almacen);
        }
        folio.setValor(folio.getValor() + 1);
        java.text.NumberFormat nf = java.text.DecimalFormat.getInstance();
        nf.setGroupingUsed(false);
        nf.setMinimumIntegerDigits(9);
        nf.setMaximumIntegerDigits(9);
        nf.setMaximumFractionDigits(0);
        StringBuilder sb = new StringBuilder();
        sb.append("TF-");
        sb.append(almacen.getEmpresa().getOrganizacion().getCodigo());
        sb.append(almacen.getEmpresa().getCodigo());
        sb.append(almacen.getCodigo());
        sb.append(nf.format(folio.getValor()));
        return sb.toString();
    }

    private String getFolio(Almacen almacen) {
        Query query = currentSession()
                .createQuery("select f from Folio f where f.nombre = :nombre and f.almacen.id = :almacenId");
        query.setString("nombre", "FACTURA");
        query.setLong("almacenId", almacen.getId());
        query.setLockOptions(LockOptions.UPGRADE);
        Folio folio = (Folio) query.uniqueResult();
        if (folio == null) {
            folio = new Folio("FACTURA");
            folio.setAlmacen(almacen);
            currentSession().save(folio);
            return getFolio(almacen);
        }
        folio.setValor(folio.getValor() + 1);
        java.text.NumberFormat nf = java.text.DecimalFormat.getInstance();
        nf.setGroupingUsed(false);
        nf.setMinimumIntegerDigits(9);
        nf.setMaximumIntegerDigits(9);
        nf.setMaximumFractionDigits(0);
        StringBuilder sb = new StringBuilder();
        sb.append("FA-");
        sb.append(almacen.getEmpresa().getOrganizacion().getCodigo());
        sb.append(almacen.getEmpresa().getCodigo());
        sb.append(almacen.getCodigo());
        sb.append(nf.format(folio.getValor()));
        return sb.toString();
    }

    private void audita(FacturaAlmacen factura, Usuario usuario, String actividad, Date fecha) {
        XFacturaAlmacen xfactura = new XFacturaAlmacen();
        BeanUtils.copyProperties(factura, xfactura);
        xfactura.setId(null);
        xfactura.setFacturaAlmacenId(factura.getId());
        xfactura.setAlmacenId(factura.getAlmacen().getId());
        xfactura.setClienteId(factura.getCliente().getId());
        xfactura.setEstatusId(factura.getEstatus().getId());
        xfactura.setFechaCreacion(fecha);
        xfactura.setActividad(actividad);
        xfactura.setCreador((usuario != null) ? usuario.getUsername() : "sistema");
        currentSession().save(xfactura);
    }

    private void audita(Salida salida, Usuario usuario, String actividad, Date fecha) {
        XSalida xsalida = new XSalida();
        BeanUtils.copyProperties(salida, xsalida);
        xsalida.setId(null);
        xsalida.setSalidaId(salida.getId());
        xsalida.setAlmacenId(salida.getAlmacen().getId());
        xsalida.setClienteId(salida.getCliente().getId());
        xsalida.setEstatusId(salida.getEstatus().getId());
        xsalida.setFechaCreacion(fecha);
        xsalida.setActividad(actividad);
        xsalida.setCreador((usuario != null) ? usuario.getUsername() : "sistema");
        currentSession().save(xsalida);
    }

    private void audita(Entrada entrada, Usuario usuario, String actividad, Date fecha) {
        XEntrada xentrada = new XEntrada();
        BeanUtils.copyProperties(entrada, xentrada);
        xentrada.setId(null);
        xentrada.setEntradaId(entrada.getId());
        xentrada.setProveedorId(entrada.getProveedor().getId());
        xentrada.setEstatusId(entrada.getEstatus().getId());
        xentrada.setAlmacenId(entrada.getAlmacen().getId());
        xentrada.setFechaCreacion(fecha);
        xentrada.setActividad(actividad);
        xentrada.setCreador((usuario != null) ? usuario.getUsername() : "sistema");
        currentSession().save(xentrada);
    }

    @Override
    @Transactional(rollbackFor = { NoEstaAbiertaException.class })
    public FacturaAlmacen agregaSalida(Long facturaId, Long salidaId) throws NoEstaAbiertaException {
        FacturaAlmacen factura = (FacturaAlmacen) currentSession().get(FacturaAlmacen.class, facturaId);
        if (factura.getEstatus().getNombre().equals(Constantes.ABIERTA)) {
            Salida salida = (Salida) currentSession().get(Salida.class, salidaId);
            factura.getSalidas().add(salida);
            factura.setTotal(factura.getTotal().add(salida.getTotal()));
            factura.setIva(factura.getIva().add(salida.getIva()));
            factura.setFechaModificacion(new Date());
            currentSession().save(factura);
            currentSession().flush();
            return factura;
        } else {
            throw new NoEstaAbiertaException("La factura no esta abierta, no se pueden agregar la salida");
        }
    }

    @Override
    @Transactional(rollbackFor = { NoEstaAbiertaException.class })
    public FacturaAlmacen agregaEntrada(Long facturaId, Long entradaId) throws NoEstaAbiertaException {
        FacturaAlmacen factura = (FacturaAlmacen) currentSession().get(FacturaAlmacen.class, facturaId);
        if (factura.getEstatus().getNombre().equals(Constantes.ABIERTA)) {
            Entrada entrada = (Entrada) currentSession().load(Entrada.class, entradaId);
            factura.getEntradas().add(entrada);
            factura.setTotal(factura.getTotal().subtract(entrada.getTotal()));
            factura.setIva(factura.getIva().subtract(entrada.getIva()));
            factura.setFechaModificacion(new Date());
            currentSession().save(factura);
            currentSession().flush();
            return factura;
        } else {
            throw new NoEstaAbiertaException("La factura no esta abierta, no se puede agregar la entrada");
        }
    }

    @Override
    @Transactional(rollbackFor = { NoEstaAbiertaException.class })
    public FacturaAlmacen eliminaSalida(Long facturaId, Long salidaId) throws NoEstaAbiertaException {
        log.debug("Eliminando salida {} de factura {}", salidaId, facturaId);
        FacturaAlmacen factura = (FacturaAlmacen) currentSession().get(FacturaAlmacen.class, facturaId);
        if (factura.getEstatus().getNombre().equals(Constantes.ABIERTA)) {
            Salida salida = (Salida) currentSession().load(Salida.class, salidaId);
            factura.setTotal(factura.getTotal().subtract(salida.getTotal()));
            factura.setIva(factura.getIva().subtract(salida.getIva()));
            log.trace("SalidasA: {}", factura.getSalidas());
            factura.getSalidas().remove(salida);
            log.trace("SalidasB: {}", factura.getSalidas());
            factura.setFechaModificacion(new Date());
            currentSession().save(factura);
            currentSession().flush();
            return factura;
        } else {
            throw new NoEstaAbiertaException("La factura no esta abierta, no se puede eliminar la salida");
        }
    }

    @Override
    @Transactional(rollbackFor = { NoEstaAbiertaException.class })
    public FacturaAlmacen eliminaEntrada(Long facturaId, Long entradaId) throws NoEstaAbiertaException {
        log.debug("Eliminando entrada {} de factura {}", entradaId, facturaId);
        FacturaAlmacen factura = (FacturaAlmacen) currentSession().get(FacturaAlmacen.class, facturaId);
        if (factura.getEstatus().getNombre().equals(Constantes.ABIERTA)) {
            Entrada entrada = (Entrada) currentSession().load(Entrada.class, entradaId);
            factura.setTotal(factura.getTotal().add(entrada.getTotal()));
            factura.setIva(factura.getIva().add(entrada.getIva()));
            factura.getEntradas().remove(entrada);
            factura.setFechaModificacion(new Date());
            currentSession().save(factura);
            currentSession().flush();
            return factura;
        } else {
            throw new NoEstaAbiertaException("La factura no esta abierta, no se puede eliminar la entrada");
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    @Transactional(readOnly = true)
    public List<Salida> salidas(Long facturaId) {
        Query query = currentSession()
                .createQuery("select s from Salida s inner join s.facturaAlmacen fa where fa.id = :facturaId");
        query.setLong("facturaId", facturaId);
        return query.list();
    }

    @Override
    @Transactional(readOnly = true)
    public List<Entrada> entradas(Long facturaId) {
        Query query = currentSession()
                .createQuery("select e from Entrada e inner join e.facturaAlmacen fa where fa.id = :facturaId");
        query.setLong("facturaId", facturaId);
        return query.list();
    }
}