/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package com.arrebol.taxiservicios.controller.cobranza;

import com.arrebol.taxiservicios.controller.admin.GenericPersonController;
import com.arrebol.taxiservicios.controller.predio.PredioController;
import com.arrebol.taxiservicios.controller.util.HibernateUtil;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.enums.EstatusLote;
import com.arrebol.taxiservicios.model.enums.EstatusPagoMultiple;
import com.arrebol.taxiservicios.model.enums.EstatusSolicitud;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.enums.TipoAbono;
import com.arrebol.taxiservicios.model.predio.AbonoLote;
import com.arrebol.taxiservicios.model.predio.AbonoLoteDetalle;
import com.arrebol.taxiservicios.model.predio.AbonoLoteView;
import com.arrebol.taxiservicios.model.predio.AbonosView;
import com.arrebol.taxiservicios.model.predio.ComentarioLote;
import com.arrebol.taxiservicios.model.predio.HitorialAbonoMultiple;
import com.arrebol.taxiservicios.model.predio.Lote;
import com.arrebol.taxiservicios.model.predio.Predio;
import com.arrebol.taxiservicios.model.predio.SolicitudDevolucionAbonoMultiple;
import com.arrebol.taxiservicios.model.predio.preCobranzaView;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 *
 * @author pc one
 */
public class CobranzaController extends GenericPersonController implements Serializable {

    private static final long serialVersionUID = -6265444716269535946L;
    final Logger logger = LogManager.getLogger(PredioController.class);

    public List<Lote> fillLoteByFolioOrCliente(String like, String idCliente) {
        logger.info("getLoteLike");
        List<Lote> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Lote..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<Lote> criteria = builder.createQuery(Lote.class);
            Root<Lote> root = criteria.from(Lote.class);

            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            if (idCliente == null || idCliente.isEmpty()) {
                Predicate criterio1 = (builder.like(root.get("folio"), "%" + like + "%"));
                criteria.where(builder.and(criterio1, criterioActivo));
            } else if (like == null || like.isEmpty()) {
                Predicate criterio1 = (builder.equal(root.get("cliente"), new Person(idCliente)));
                criteria.where(builder.and(criterio1, criterioActivo));
            } else {
                Predicate criterio1 = (builder.like(root.get("folio"), "%" + like + "%"));
                Predicate criterio2 = (builder.equal(root.get("cliente"), new Person(idCliente)));
                criteria.where(builder.and(criterio1, criterio2, criterioActivo));
            }
            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of lotes found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Lotes cannot be loaded " + like, e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method getLoteLike(" + like + ") ", e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<Lote> fillLoteVendidoByCliente(String idCliente) {
        logger.info("fillLoteByCliente");
        List<Lote> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Lote..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<Lote> criteria = builder.createQuery(Lote.class);
            Root<Lote> root = criteria.from(Lote.class);

            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate criterioEstatusLote = builder.equal(root.get("estatusLote"), EstatusLote.VENDIDO);
            Predicate criterio = (builder.equal(root.get("cliente"), new Person(idCliente)));
            criteria.where(builder.and(criterio, criterioActivo, criterioEstatusLote));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of lotes found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Lotes cannot be loaded ");
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillLoteByCliente ", e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLote> fillAbonoLoteByLote(Lote lote) {
        List<AbonoLote> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Lote.." + lote.getId());
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLote> criteria = builder.createQuery(AbonoLote.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);

            Predicate criterio = (builder.equal(root.get("lote"), lote));
            Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
            Predicate criterio3 = (builder.equal(root.get("tipoAbono"), TipoAbono.ABONO));
            criteria.where(builder.and(criterio, criterio2, criterio3));
            criteria.orderBy(builder.asc(root.get("fechaAPagar")));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteByLote() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLote> fillAbonoAndAnticipoLoteByLote(Lote lote) {
        List<AbonoLote> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Lote.." + lote.getId());
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLote> criteria = builder.createQuery(AbonoLote.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);

            Predicate criterio = (builder.equal(root.get("lote"), lote));
            Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
            criteria.where(builder.and(criterio, criterio2));
            criteria.orderBy(builder.asc(root.get("fechaAPagar")));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoAndAnticipoLoteByLote() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLoteDetalle> fillAbonoLoteDetalleLoteByAbonoLote(AbonoLote ab) {
        List<AbonoLoteDetalle> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching abonos detalle for abono.." + ab.getId());
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLoteDetalle> criteria = builder.createQuery(AbonoLoteDetalle.class);
            Root<AbonoLoteDetalle> root = criteria.from(AbonoLoteDetalle.class);

            Predicate criterio = (builder.equal(root.get("abonoLote").get("id"), ab.getId()));
            Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
            criteria.where(builder.and(criterio, criterio2));
            criteria.orderBy(builder.asc(root.get("createdOn")));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of abonos detalle found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteDetalleLoteByAbonoLote() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLoteView> fillAbonoLoteViewByLote(Lote lote) {
        List<AbonoLoteView> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching AbonoLoteView for Lote.." + lote.getId());
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLoteView> criteria = builder.createQuery(AbonoLoteView.class);
            Root<AbonoLoteView> root = criteria.from(AbonoLoteView.class);

            Predicate criterio = (builder.equal(root.get("lote"), lote));
            Predicate criterio2 = (builder.equal(root.get("tipoAbono"), TipoAbono.ABONO));
            Predicate criterio3 = (builder.equal(root.get("tipoAbono"), TipoAbono.SUBABONO));
            criteria.where(builder.and(criterio), builder.or(criterio2, criterio3));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method AbonoLoteView() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLote> fillAbonoLoteByLoteAndTipo(Lote lote, TipoAbono tipo) {
        List<AbonoLote> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Lote.." + lote.getId());
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLote> criteria = builder.createQuery(AbonoLote.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);

            Predicate criterio = (builder.equal(root.get("lote"), lote));
            Predicate criterioTipo = (builder.equal(root.get("tipoAbono"), tipo));
            Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
            criteria.where(builder.and(criterio, criterio2, criterioTipo));
            criteria.orderBy(builder.asc(root.get("fechaAPagar")));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteByLote() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLote> fillAbonoLoteByLoteNoPay(Lote lote) {
        List<AbonoLote> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Lote.." + lote.getId());
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLote> criteria = builder.createQuery(AbonoLote.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);

            Predicate criterio = (builder.equal(root.get("lote"), lote));
            Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));

            Predicate criterio3 = builder.equal(root.get("pagoEstatus"), GenericEnumType.DISABLED);
            Predicate criterio4 = builder.equal(root.get("pagoEstatus"), GenericEnumType.INCOMPLETE);

            criteria.where(builder.and(criterio, criterio2), builder.or(criterio3, criterio4));
            criteria.orderBy(builder.asc(root.get("fechaAPagar")));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteByLote() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLote> fillAbonoLoteByLoteIncomplete(Lote lote) {
        List<AbonoLote> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Lote.." + lote.getId());
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLote> criteria = builder.createQuery(AbonoLote.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);

            Predicate criterio = (builder.equal(root.get("lote"), lote));
            Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
            Predicate criterio3 = builder.greaterThan(root.get("diferenciaPago"), 0D);

            criteria.where(builder.and(criterio, criterio2, criterio3));
            criteria.orderBy(builder.asc(root.get("fechaAPagar")));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteByLote() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLote> fillAbonoLoteByLoteNoExtraAndPagoEstatusAndMensualidad(Lote lote, GenericEnumType pagoEstatus, Double extra) {
        List<AbonoLote> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Lote.." + lote.getId());
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLote> criteria = builder.createQuery(AbonoLote.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);

            Predicate criterio = (builder.equal(root.get("lote"), lote));
            Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
            Predicate criterio3 = (builder.equal(root.get("pagoEstatus"), pagoEstatus));
            Predicate criterio4 = (builder.notEqual(root.get("pago"), extra));
            criteria.where(builder.and(criterio, criterio2, criterio3, criterio4));
            criteria.orderBy(builder.asc(root.get("fechaAPagar")));

            resultList = session.createQuery(criteria).getResultList();
            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteByLote() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLote> fillAbonoLoteExtraByLoteAndPagoEstatusAndMensualidad(Lote lote, GenericEnumType pagoEstatus, Double mensualidad) {
        List<AbonoLote> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Lote.." + lote.getId());
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLote> criteria = builder.createQuery(AbonoLote.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);

            Predicate criterio = (builder.equal(root.get("lote"), lote));
            Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
            Predicate criterio3 = (builder.equal(root.get("pagoEstatus"), pagoEstatus));
            Predicate criterio4 = (builder.notEqual(root.get("pago"), mensualidad));
            Predicate criterio5 = (builder.equal(root.get("convenio"), 0));
            criteria.where(builder.and(criterio, criterio2, criterio3, criterio4, criterio5));
            criteria.orderBy(builder.asc(root.get("fechaAPagar")));

            resultList = session.createQuery(criteria).getResultList();
            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteByLote() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<ComentarioLote> fillComentariosLote(Lote lote) {
        List<ComentarioLote> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for comentario Lote.." + lote.getId());
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<ComentarioLote> criteria = builder.createQuery(ComentarioLote.class);
            Root<ComentarioLote> root = criteria.from(ComentarioLote.class);

            Predicate criterio = (builder.equal(root.get("lote"), lote));

            criteria.where(builder.and(criterio));
            criteria.orderBy(builder.asc(root.get("createdOn")));

            resultList = session.createQuery(criteria).getResultList();
            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteByLote() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public AbonoLote fillLastUpdateAbonoLoteByLote(Lote lote) {
        AbonoLote lastAbonoLote = null;
        List<AbonoLote> resultList;
        Transaction transaction = null;
        try {
            logger.info("Searching for Lote.." + lote.getId());
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLote> criteria = builder.createQuery(AbonoLote.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);

            Predicate criterio = builder.equal(root.get("lote"), lote);
            Predicate criterio2 = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            criteria.where(builder.and(criterio, criterio2));
            criteria.orderBy(builder.desc(root.get("lastUpdatedOn"))); // Ordenar por lastUpdatedOn en orden descendente

            resultList = session.createQuery(criteria).getResultList();
            if (!resultList.isEmpty()) {
                lastAbonoLote = resultList.get(0); // Obtener el primer resultado que será el último registro actualizado
            }

            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteByLote() " + e);
            rollback(transaction);
        }
        return lastAbonoLote;
    }

    public List<AbonoLote> fillAbonoLoteByIdCliente(String idCliente) {
        List<AbonoLote> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Lote..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLote> criteria = builder.createQuery(AbonoLote.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);

            Predicate criterio = (builder.equal(root.get("cliente").get("id"), idCliente));
            Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
            criteria.where(builder.and(criterio, criterio2));
            criteria.orderBy(builder.asc(root.get("fechaAPagar")));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteByIdCliente() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public boolean addAbonoLote(AbonoLote abono, User user, boolean save) {
        logger.info("addLote");
        boolean success = false;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            if (save) {
                abono.setCreatedBy(user);
                abono.setCreatedOn(new Date());
                session.save(abono);
                transaction.commit();
                logger.info("Abono saved " + abono.getId());
            } else {
                abono.setLastUpdatedBy(user);
                if (abono.getPagoEstatus().equals(GenericEnumType.INCOMPLETE)) {
                    if (abono.getDiferenciaPago() == 0) {
                        abono.setPagoEstatus(GenericEnumType.ENABLED);
                    }

                } else if (abono.getPagoEstatus().equals(GenericEnumType.ENABLED)) {
                    abono.setLastUpdatedOn(new Date());

                }
                session.update(abono);
                transaction.commit();
                logger.info("Abono updated " + abono.getId());
            }

            success = true;
        } catch (HibernateException e) {
            logger.error("Abono can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addAbonoLote() ", e);
            rollback(transaction);
        }
        return success;
    }

    public boolean addHitorialAbonoMultiple(HitorialAbonoMultiple abonoMultiple, User user, boolean save) {
        logger.info("addHitorialAbonoMultiple");
        boolean success = false;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            if (save) {
                abonoMultiple.setCreatedBy(user);
                abonoMultiple.setCreatedOn(new Date());
                session.save(abonoMultiple);
                transaction.commit();
                logger.info("Abono saved " + abonoMultiple.getId());
            } else {
                abonoMultiple.setLastUpdatedOn(new Date());
                abonoMultiple.setLastUpdatedBy(user);
                session.update(abonoMultiple);
                transaction.commit();
                logger.info("Hitorial Abono Multiple updated " + abonoMultiple.getId());
            }

            success = true;
        } catch (HibernateException e) {
            logger.error("Hitorial Abono Multiple can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addHitorialAbonoMultiple() ", e);
            rollback(transaction);
        }
        return success;
    }

    public List<HitorialAbonoMultiple> fillHitorialAbonoMultipleByLote(String idLote, String idLocation) {
        logger.info("fillHitorialAbonoMultipleByLote");
        List<HitorialAbonoMultiple> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Hitorial Abono Multiple..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<HitorialAbonoMultiple> criteria = builder.createQuery(HitorialAbonoMultiple.class);
            Root<HitorialAbonoMultiple> root = criteria.from(HitorialAbonoMultiple.class);

            Predicate criterio = (builder.equal(root.get("lote").get("id"), idLote));
            Predicate criterio2 = (builder.equal(root.get("location").get("id"), idLocation));
            criteria.where(builder.and(criterio, criterio2));
            criteria.orderBy(builder.asc(root.get("createdOn")));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of Hitorial Abono Multiple found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Hitorial Abono Multiple cannot be loaded ");
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillHitorialAbonoMultipleByLote ", e);
            rollback(transaction);
        }
        return resultList;
    }
    
        public HitorialAbonoMultiple fillHitorialAbonoMultipleById(String idAbonoMultiple) {
        logger.info("fillHitorialAbonoMultipleById");
        HitorialAbonoMultiple result = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Hitorial Abono Multiple..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<HitorialAbonoMultiple> criteria = builder.createQuery(HitorialAbonoMultiple.class);
            Root<HitorialAbonoMultiple> root = criteria.from(HitorialAbonoMultiple.class);

            Predicate criterio = (builder.equal(root.get("id"), idAbonoMultiple));            
            criteria.where(builder.and(criterio));            

            result = session.createQuery(criteria).getSingleResult();

            logger.info("Hitorial Abono Multiple found: "+ result.getId());
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Hitorial Abono Multiple cannot be loaded ");
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillHitorialAbonoMultipleById ", e);
            rollback(transaction);
        }
        return result;
    }

    public List<AbonoLote> fillAbonoLoteByHitorialAbonoMultiple(String idHitorialAbonoMultiple) {
        logger.info("fillAbonoLoteByHitorialAbonoMultiple");
        List<AbonoLote> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Hitorial Abono Multiple..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLote> criteria = builder.createQuery(AbonoLote.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);

            Predicate criterio = (builder.equal(root.get("abonoMultiple").get("id"), idHitorialAbonoMultiple));
            criteria.where(builder.and(criterio));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of Abono Lote found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abono Lote cannot be loaded ");
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteByHitorialAbonoMultiple ", e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLoteDetalle> fillAbonoLoteDetalleByHitorialAbonoMultiple(String idAbonoMultiple, String idAbonoLote) {
        logger.info("fillAbonoLoteDetalleByHitorialAbonoMultiple");
        List<AbonoLoteDetalle> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Hitorial Abono Multiple..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLoteDetalle> criteria = builder.createQuery(AbonoLoteDetalle.class);
            Root<AbonoLoteDetalle> root = criteria.from(AbonoLoteDetalle.class);

            Predicate criterio = (builder.equal(root.get("abonoMultiple").get("id"), idAbonoMultiple));
            Predicate criterio2 = (builder.equal(root.get("abonoLote").get("id"), idAbonoLote));
            criteria.where(builder.and(criterio, criterio2));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of Abono Lote Detalle found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abono Lote Detalle cannot be loaded ");
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteDetalleByHitorialAbonoMultiple ", e);
            rollback(transaction);
        }
        return resultList;
    }

    public boolean addSolicitudDevolucionAbonoMultiple(SolicitudDevolucionAbonoMultiple solicitud, User user, boolean save) {
        logger.info("addSolicitudDevolucionAbonoMultiple");
        boolean success = false;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            if (save) {
                solicitud.setId(UUID.randomUUID().toString());
                solicitud.setCreatedBy(user);
                solicitud.setCreatedOn(new Date());
                session.save(solicitud);
                transaction.commit();
                logger.info("Solicitud saved " + solicitud.getId());
            } else {
                solicitud.setLastUpdatedOn(new Date());
                solicitud.setLastUpdatedBy(user);
                session.update(solicitud);
                transaction.commit();
                logger.info("Solicitud updated " + solicitud.getId());
            }

            success = true;
        } catch (HibernateException e) {
            logger.error("Solicitud can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addSolicitudDevolucionAbonoMultiple() ", e);
            rollback(transaction);
        }
        return success;
    }

    public List<SolicitudDevolucionAbonoMultiple> fillSolicitudDevolucionAbonoMultipleByLocation(String idLocation) {
        logger.info("fillHitorialAbonoMultipleByLote");
        List<SolicitudDevolucionAbonoMultiple> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for Hitorial Abono Multiple..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<SolicitudDevolucionAbonoMultiple> criteria = builder.createQuery(SolicitudDevolucionAbonoMultiple.class);
            Root<SolicitudDevolucionAbonoMultiple> root = criteria.from(SolicitudDevolucionAbonoMultiple.class);

            Predicate criterio = (builder.equal(root.get("location").get("id"), idLocation));
            Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
            criteria.where(builder.and(criterio, criterio2));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of Hitorial Abono Multiple found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Hitorial Abono Multiple cannot be loaded ");
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillHitorialAbonoMultipleByLote ", e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<SolicitudDevolucionAbonoMultiple> fillSolicitudDevolucionAbonoMultipleByLocationAndHitorialAbonoMultipleAndEstatus(String idLocation, HitorialAbonoMultiple abonoMultiple, EstatusSolicitud estatus) {
        logger.info("fillSolicitudDevolucionAbonoMultipleByLocationAndHitorialAbonoMultipleAndEstatus");
        List<SolicitudDevolucionAbonoMultiple> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching solicitud for Hitorial Abono Multiple..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<SolicitudDevolucionAbonoMultiple> criteria = builder.createQuery(SolicitudDevolucionAbonoMultiple.class);
            Root<SolicitudDevolucionAbonoMultiple> root = criteria.from(SolicitudDevolucionAbonoMultiple.class);

            Predicate criterio = (builder.equal(root.get("location").get("id"), idLocation));
            Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
            Predicate criterio3 = (builder.equal(root.get("estatusSolicitud"), estatus));
            Predicate criterio4 = (builder.equal(root.get("hitorialAbonoMultiple").get("id"), abonoMultiple.getId()));
            criteria.where(builder.and(criterio, criterio2, criterio3, criterio4));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total solicitud of Hitorial Abono Multiple found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Solicitud for Hitorial Abono Multiple cannot be loaded ");
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillSolicitudDevolucionAbonoMultipleByLocationAndHitorialAbonoMultipleAndEstatus ", e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLoteView> fillAbonoLoteViewByAbonoMultiple(String idAbonoMultiple) {
        List<AbonoLoteView> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching AbonoLoteView for Abono Multiple.." + idAbonoMultiple);
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLoteView> criteria = builder.createQuery(AbonoLoteView.class);
            Root<AbonoLoteView> root = criteria.from(AbonoLoteView.class);

            Predicate criterio = (builder.equal(root.get("abonoMultiple").get("id"), idAbonoMultiple));
            criteria.where(builder.and(criterio));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteViewByAbonoMultiple() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public boolean addAbonoLoteDetalle(AbonoLoteDetalle abono, User user) {
        logger.info("addLote");
        boolean success = false;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            abono.setId(UUID.randomUUID().toString());
            abono.setEstatusActivo(GenericEnumType.ENABLED);
            abono.setCreatedBy(user);
            abono.setCreatedOn(new Date());
            session.save(abono);
            transaction.commit();
            logger.info("Abono saved " + abono.getId());

            success = true;
        } catch (HibernateException e) {
            logger.error("Abono can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addAbonoLote() ", e);
            rollback(transaction);
        }
        return success;
    }

    public boolean updateAbonoLoteDetalle(AbonoLoteDetalle abono, User user) {
        logger.info("update AbonoLoteDetalle");
        boolean success = false;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            abono.setLastUpdatedBy(user);
            abono.setLastUpdatedOn(new Date());
            session.update(abono);
            transaction.commit();
            logger.info("Abono update " + abono.getId());

            success = true;
        } catch (HibernateException e) {
            logger.error("Abono can not be update ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method updateAbonoLoteDetalle() ", e);
            rollback(transaction);
        }
        return success;
    }

    public boolean addComentarioLote(ComentarioLote comentario, User user) {
        logger.info("addComentarioLote");
        boolean success = false;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            comentario.setId(UUID.randomUUID().toString());
            comentario.setCreatedBy(user);
            comentario.setCreatedOn(new Date());
            session.save(comentario);
            transaction.commit();
            logger.info("Comentario saved " + comentario.getId());

            success = true;
        } catch (HibernateException e) {
            logger.error("Cometario can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addComentarioLote() ", e);
            rollback(transaction);
        }
        return success;
    }

    public boolean addAbonoLoteWithJuridico(AbonoLote abono, User user, boolean save) {
        logger.info("addLote");
        boolean success = false;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            if (save) {
                abono.setCreatedBy(user);
                abono.setCreatedOn(new Date());
                session.save(abono);
                transaction.commit();
                logger.info("Abono saved " + abono.getId());
            } else {
                abono.setLastUpdatedBy(user);
                abono.setLastUpdatedOn(new Date());
                abono.setPagoJuridico(1);
                session.update(abono);
                transaction.commit();
                logger.info("Abono updated " + abono.getId());
            }

            success = true;
        } catch (HibernateException e) {
            logger.error("Abono can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addAbonoLote() ", e);
            rollback(transaction);
        }
        return success;
    }

    public List<preCobranzaView> fillPreCobranzaViewByFecha(Date startDate, Date endDate, Location location) {
        List<preCobranzaView> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for startDate and endDate..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            String query = "SELECT pre FROM preCobranzaView pre "
                    + "WHERE DATE(pre.fechaAPagar) BETWEEN DATE(:startDate) AND DATE(:endDate) "
                    + "AND pagoEstatus = 'DISABLED' AND location=:location";
            resultList = session.createQuery(query)
                    .setParameter("startDate", startDate)
                    .setParameter("endDate", endDate)
                    .setParameter("location", location)
                    .getResultList();

            logger.info("Total of Pre Cobranza View found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Pre Cobranza View cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillPreCobranzaViewByFecha() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public long countPagosByLote(String idLote) {
        logger.info("Counting abonos...");
        long count = 0;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);
            criteria.select(builder.count(root));
            criteria.where(
                    builder.equal(root.get("lote").get("id"), idLote),
                    builder.equal(root.get("pagoEstatus"), GenericEnumType.ENABLED),
                    builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED),
                    builder.equal(root.get("tipoAbono"), TipoAbono.ABONO)
            );
            count = session.createQuery(criteria).getSingleResult();
            logger.info("Total of abonos found: " + count);
            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Unable to count abonos", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method countPagosByLote", e);
        }
        return count;
    }

    public Double sumAbonoLote(String idPredio, Date startDate, Date endDate) {
        logger.info("Counting abonos...");
        Double count = 0D;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Double> criteria = builder.createQuery(Double.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);

            LocalDate localStartDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate localEndDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

            criteria.select(builder.sum(root.get("cantidadPagada")));
            criteria.where(
                    builder.equal(root.get("lote").get("manzana").get("predio").get("id"), idPredio),
                    builder.equal(root.get("pagoEstatus"), GenericEnumType.ENABLED),
                    builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED),
                    builder.equal(root.get("tipoAbono"), TipoAbono.ABONO),
                    builder.greaterThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localStartDate),
                    builder.lessThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localEndDate)
            );
            count = session.createQuery(criteria).getSingleResult();
            logger.info("Total of abonos found: " + count);
            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Unable to count abonos", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method countPagosByLote", e);
        }
        return count == null ? 0D : count;
    }

    public Double sumAbonoLoteDetalle(String idPredio, Date startDate, Date endDate) {
        logger.info("Counting abonos...");
        Double count = 0D;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Double> criteria = builder.createQuery(Double.class);
            Root<AbonoLoteDetalle> root = criteria.from(AbonoLoteDetalle.class);

            LocalDate localStartDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate localEndDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

            criteria.select(builder.sum(root.get("pago")));
            criteria.where(
                    builder.equal(root.get("abonoLote").get("lote").get("manzana").get("predio").get("id"), idPredio),
                    builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED),
                    builder.greaterThanOrEqualTo(root.get("createdOn").as(LocalDate.class), localStartDate),
                    builder.lessThanOrEqualTo(root.get("createdOn").as(LocalDate.class), localEndDate)
            );
            count = session.createQuery(criteria).getSingleResult();
            logger.info("Total of abonos found: " + count);
            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Unable to count abonos", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method countPagosByLote", e);
        }
        return count == null ? 0D : count;
    }

    public boolean existsIncompleteBefore(AbonoLote abonoLote) {
        logger.info("existIncompleteBefore");
        boolean success = true;
        Transaction transaction = null;
        long count = 0;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);
            criteria.select(builder.count(root));

            Predicate criterio = (builder.equal(root.get("lote"), abonoLote.getLote()));
            Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
            Predicate criterio3 = builder.lessThan(root.get("fechaAPagar"), abonoLote.getFechaAPagar());
            Predicate criterio4 = builder.equal(root.get("tipoAbono"), TipoAbono.ABONO);
            Predicate criterio5 = builder.equal(root.get("pagoEstatus"), GenericEnumType.DISABLED);
            Predicate criterio6 = builder.equal(root.get("pagoEstatus"), GenericEnumType.INCOMPLETE);
            Predicate criterio7 = builder.or(criterio5, criterio6);
            criteria.where(builder.and(criterio, criterio2, criterio3, criterio4, criterio7));
            count = session.createQuery(criteria).getSingleResult();

            if (count == 0) {
                success = false;
            }
            logger.info("Total of abonos found: " + count);
            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Unable to count abonos", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method countPagosByLote", e);
        }
        return success;
    }

    public List<AbonoLoteView> fillAbonoLoteAndSubAbonoByLoteAndTipo(Lote lote, TipoAbono tipo) {
        List<AbonoLoteView> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for AbonoLoteView..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLoteView> criteria = builder.createQuery(AbonoLoteView.class);
            Root<AbonoLoteView> root = criteria.from(AbonoLoteView.class);

            Predicate criterio = (builder.equal(root.get("lote"), lote));
            Predicate criterioTipo1 = (builder.equal(root.get("tipoAbono"), tipo));
            Predicate criterioTipo2 = (builder.equal(root.get("tipoAbono"), TipoAbono.SUBABONO));

            criteria.where(builder.and(criterio), builder.or(criterioTipo1, criterioTipo2));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method AbonoLoteView() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLoteView> fillAbonoLoteAndSubAbonoByPredioAndDates(Predio predio, TipoAbono tipo, Date startDate, Date endDate) {
        List<AbonoLoteView> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for AbonoLoteView..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLoteView> criteria = builder.createQuery(AbonoLoteView.class);
            Root<AbonoLoteView> root = criteria.from(AbonoLoteView.class);

            Predicate criterioTipo1 = (builder.equal(root.get("tipoAbono"), tipo));
            Predicate criterioTipo2 = (builder.equal(root.get("tipoAbono"), TipoAbono.SUBABONO));
            Predicate criterio = builder.equal(root.get("lote").get("manzana").get("predio"), predio);
            Predicate criterio2 = builder.equal(root.get("pagoEstatus"), GenericEnumType.ENABLED);

            Predicate criterioFecha1 = builder.greaterThanOrEqualTo(root.get("lastUpdatedOn"), startDate);
            Predicate criterioFecha2 = builder.lessThanOrEqualTo(root.get("lastUpdatedOn"), endDate);

            criteria.where(builder.and(criterio, criterio2, criterioFecha1, criterioFecha2), builder.or(criterioTipo1, criterioTipo2));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method AbonoLoteView() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLoteView> fillAbonoLoteAndSubAbonoByPredioAndDatesOrderByfolio(Predio predio, TipoAbono tipo, Date startDate, Date endDate) {
        List<AbonoLoteView> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching for AbonoLoteView..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLoteView> criteria = builder.createQuery(AbonoLoteView.class);
            Root<AbonoLoteView> root = criteria.from(AbonoLoteView.class);

            LocalDate localStartDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate localEndDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

            Predicate criterioTipo1 = (builder.equal(root.get("tipoAbono"), tipo));
            Predicate criterioTipo2 = (builder.equal(root.get("tipoAbono"), TipoAbono.SUBABONO));
            Predicate criterio = builder.equal(root.get("lote").get("manzana").get("predio"), predio);
            Predicate criterio2 = builder.equal(root.get("pagoEstatus"), GenericEnumType.ENABLED);

            Predicate criterioFecha1 = builder.greaterThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localStartDate);
            Predicate criterioFecha2 = builder.lessThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localEndDate);

            criteria.where(builder.and(criterio, criterio2, criterioFecha1, criterioFecha2), builder.or(criterioTipo1, criterioTipo2));
            criteria.orderBy(builder.asc(root.get("folio")), builder.asc(root.get("lastUpdatedOn")));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method AbonoLoteView() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public List<AbonoLote> fillAbonoLoteByFolioAndProyecto(String idPredio, String abreviacionFolio) {
        List<AbonoLote> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching abonos lote..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

            CriteriaQuery<AbonoLote> criteria = builder.createQuery(AbonoLote.class);
            Root<AbonoLote> root = criteria.from(AbonoLote.class);

            Predicate criterio = (builder.equal(root.get("lote").get("manzana").get("predio").get("id"), idPredio));
            Predicate criterio1 = (builder.like(root.get("folio"), "%" + abreviacionFolio + "%"));
            criteria.where(builder.and(criterio, criterio1));
            criteria.orderBy(builder.asc(root.get("fechaAPagar")));

            resultList = session.createQuery(criteria).getResultList();

            logger.info("Total of abonos found: " + (null == resultList ? -1 : resultList.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonoLoteByFolioAndProyecto() " + e);
            rollback(transaction);
        }
        return resultList;
    }

    public AbonosView fillAbonosViewByFolioAndProyecto(String idPredio, String abreviacionFolio) {
        AbonosView result = null;

        Transaction transaction = null;
        try {
            logger.info("Searching abonos lote..");
            
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            String query = "SELECT ab FROM AbonosView ab "
                    + "WHERE ab.predio.id = :idPredio "
                    + "AND ab.tipo != 'URBANIZACION' "
                    + "AND ab.folio LIKE '" + abreviacionFolio + "%' "
                    + "ORDER BY "
                    + "SUBSTRING_INDEX(ab.folio, '-', 1) DESC, "
                    + "SUBSTRING_INDEX(SUBSTRING_INDEX(ab.folio, '-', -1), '-', -6) DESC ";

            result = (AbonosView) session.createQuery(query)
                    .setParameter("idPredio", idPredio)
                    .setMaxResults(1)
                    .uniqueResult();
            
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonosViewByFolioAndProyecto() " + e);
            rollback(transaction);
        }
        return result;
    }

    public AbonosView fillURBANIZACIONAbonosViewByFolioAndProyecto(String idPredio, String abreviacionFolio) {
        AbonosView result = null;
        Transaction transaction = null;
        try {
            logger.info("Searching abonos lote..");

            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            String query = "SELECT ab FROM AbonosView ab "
                    + "WHERE ab.predio.id = :idPredio "
                    + "AND ab.tipo = 'URBANIZACION' "
                    + "AND ab.folio LIKE '" + abreviacionFolio + "%' "
                    + "ORDER BY "
                    + "SUBSTRING_INDEX(ab.folio, '-', 1) DESC, "
                    + "SUBSTRING_INDEX(SUBSTRING_INDEX(ab.folio, '-', -1), '-', -6) DESC ";

            result = (AbonosView) session.createQuery(query)
                    .setParameter("idPredio", idPredio)
                    .setMaxResults(1)
                    .uniqueResult();

            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Abonos cannot be loaded " + e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAbonosViewByFolioAndProyecto() " + e);
            rollback(transaction);
        }
        return result;
    }

}
