/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.arrebol.taxiservicios.controller.predio;

import com.arrebol.taxiservicios.controller.admin.*;
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.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.Lote;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate;
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 Picasso
 */
public class LoteController extends GenericPersonController implements Serializable {

    private static final long serialVersionUID = -6265444716269535946L;

    final Logger logger = LogManager.getLogger(LoteController.class);

    public Lote fillLote(String id) {
        Transaction transaction = null;
        Lote result = null;

        try {
            logger.info("Searching 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 criterio = builder.equal(root.get("id"), id);
            criteria.where(builder.and(criterio));

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

            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Can not load lote", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillLote ", e);
            rollback(transaction);
        }

        return result;
    }

    public Long contarLotesDisponibles(Location location) {
        logger.info("contarLoresDisponbles");
        Long conteo = 0L;

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

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
            Root<Lote> root = criteria.from(Lote.class);
            criteria.select(builder.count(root));
            Predicate criterioLocation = builder.equal(root.get("manzana").get("predio").get("location"), location);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate tipoPredicate = builder.equal(root.get("estatusLote"), EstatusLote.DISPONIBLE);
            Predicate tipoEstatusProyecto = builder.equal(root.get("manzana").get("predio").get("estatusActivo"), GenericEnumType.ENABLED);
            criteria.where(builder.and(criterioLocation, tipoPredicate, criterioActivo, tipoEstatusProyecto));

            conteo = session.createQuery(criteria).getSingleResult();
            transaction.commit();

            logger.info("Lotes disponibles encontrados " + conteo);

        } catch (HibernateException e) {
            logger.error("Abono can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addAbonoProyecto() ", e);
            rollback(transaction);
        }

        return conteo;

    }

    public Long contarLotesByLocation(Location location) {
        logger.info("contarLoresDisponbles");
        Long conteo = 0L;

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

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
            Root<Lote> root = criteria.from(Lote.class);
            criteria.select(builder.count(root));
            Predicate criterioLocation = builder.equal(root.get("manzana").get("predio").get("location"), location);
            Predicate criterioEstatusProyecto = builder.equal(root.get("manzana").get("predio").get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            criteria.where(builder.and(criterioLocation, criterioActivo, criterioEstatusProyecto));

            conteo = session.createQuery(criteria).getSingleResult();
            transaction.commit();

            logger.info("Lotes disponibles encontrados " + conteo);

        } catch (HibernateException e) {
            logger.error("Abono can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addAbonoProyecto() ", e);
            rollback(transaction);
        }

        return conteo;

    }

    public List<Lote> fillAllLotesDisponibles() {
        logger.info("fillLoteByFolioOrCliente");
        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 tipoPredicate = builder.equal(root.get("estatusLote"), EstatusLote.DISPONIBLE);
            Predicate tipoEstatusProyecto = builder.equal(root.get("manzana").get("predio").get("estatusActivo"), GenericEnumType.ENABLED);
            criteria.where(builder.and(tipoPredicate, criterioActivo, tipoEstatusProyecto));
            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 ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillLoteByFolioOrCliente ", e);
            rollback(transaction);
        }
        return resultList;
    }

    public Long contarLotesApartados(Location location) {
        logger.info("contarLotesApartados");
        Long conteo = 0L;

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

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
            Root<Lote> root = criteria.from(Lote.class);
            criteria.select(builder.count(root));
            Predicate criterioLocation = builder.equal(root.get("manzana").get("predio").get("location"), location);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate tipoPredicate = builder.equal(root.get("estatusLote"), EstatusLote.APARTADO);
            Predicate tipoEstatusProyecto = builder.equal(root.get("manzana").get("predio").get("estatusActivo"), GenericEnumType.ENABLED);
            criteria.where(builder.and(criterioLocation, tipoPredicate, criterioActivo, tipoEstatusProyecto));

            conteo = session.createQuery(criteria).getSingleResult();
            transaction.commit();

            logger.info("Lotes Apartados encontrados " + conteo);

        } catch (HibernateException e) {
            logger.error("Abono can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addAbonoProyecto() ", e);
            rollback(transaction);
        }

        return conteo;

    }

    public Long contarLoteVendido(Location location) {
        logger.info("contarLoteVendido");
        Long conteo = 0L;

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

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
            Root<Lote> root = criteria.from(Lote.class);
            criteria.select(builder.count(root));
            Predicate criterioLocation = builder.equal(root.get("manzana").get("predio").get("location"), location);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate tipoPredicate = builder.equal(root.get("estatusLote"), EstatusLote.VENDIDO);
            Predicate tipoEstatusProyecto = builder.equal(root.get("manzana").get("predio").get("estatusActivo"), GenericEnumType.ENABLED);
            criteria.where(builder.and(criterioLocation, tipoPredicate, criterioActivo, tipoEstatusProyecto));

            conteo = session.createQuery(criteria).getSingleResult();
            transaction.commit();

            logger.info("Lotes vendidos encontredos " + conteo);

        } catch (HibernateException e) {
            logger.error("Abono can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addAbonoProyecto() ", e);
            rollback(transaction);
        }

        return conteo;

    }
    
    public Long contarLoteLiquidado(Location location) {
        logger.info("contarLoteVendido");
        Long conteo = 0L;

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

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
            Root<Lote> root = criteria.from(Lote.class);
            criteria.select(builder.count(root));
            Predicate criterioLocation = builder.equal(root.get("manzana").get("predio").get("location"), location);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate tipoPredicate = builder.equal(root.get("estatusLote"), EstatusLote.LIQUIDADO);
            Predicate tipoEstatusProyecto = builder.equal(root.get("manzana").get("predio").get("estatusActivo"), GenericEnumType.ENABLED);
            criteria.where(builder.and(criterioLocation, tipoPredicate, criterioActivo, tipoEstatusProyecto));

            conteo = session.createQuery(criteria).getSingleResult();
            transaction.commit();

            logger.info("Lotes vendidos encontredos " + conteo);

        } catch (HibernateException e) {
            logger.error("Abono can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addAbonoProyecto() ", e);
            rollback(transaction);
        }

        return conteo;

    }

    public Long contarAbonoAVencerTresDias(Date fechaInicial, Date fechaFinal, Location location) {
        logger.info("contarAbonoAVencerTresDias");
        Long conteo = 0L;

        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));

            LocalDate localStartDate = fechaInicial.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate localEndDate = fechaFinal.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);

            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate estatusPredicate = builder.equal(root.get("pagoEstatus"), GenericEnumType.DISABLED);
            Predicate fechaInicialPredicate = builder.greaterThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localStartDate);
            Predicate fechaFinalPredicate = builder.lessThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localEndDate);

            criteria.where(builder.and(criterioLocation, estatusPredicate, fechaInicialPredicate, fechaFinalPredicate, criterioActivo));

            conteo = session.createQuery(criteria).getSingleResult();
            transaction.commit();

            logger.info("Abonos a vencer en tres dias " + conteo);

        } catch (HibernateException e) {
            logger.error("Abono can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addAbonoProyecto() ", e);
            rollback(transaction);
        }

        return conteo;

    }

    public List<AbonoLote> fillAllAbonoAVencerTresDias(Date fechaInicial, Date fechaFinal, Location location) {
        Transaction transaction = null;
        List<AbonoLote> result = null;

        try {
            logger.info("Searching all Abonos A Venceren Tres Dias..");
            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);

            LocalDate localStartDate = fechaInicial.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate localEndDate = fechaFinal.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);
            Predicate estatusPredicate = builder.equal(root.get("pagoEstatus"), GenericEnumType.DISABLED);
            Predicate fechaInicialPredicate = builder.greaterThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localStartDate);
            Predicate fechaFinalPredicate = builder.lessThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localEndDate);

            criteria.where(builder.and(estatusPredicate, criterioLocation, fechaInicialPredicate, fechaFinalPredicate, criterioActivo));
            criteria.orderBy(builder.asc(root.get("createdOn")));

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

            logger.info("Total of Abonos A Venceren Tres Dias found: " + (null == result ? -1 : result.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Can not load list of Abonos A Venceren Tres Dias", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAllAbonoAVencerTresDias", e);
            rollback(transaction);
        }

        return result;
    }

    public Long contarAbonosVencidos(Date fechaInicial, Location location) {
        logger.info("contarAbonosVencidos");
        Long conteo = 0L;

        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));
            LocalDate localStartDate = fechaInicial.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate estatusPredicate = builder.equal(root.get("pagoEstatus"), GenericEnumType.DISABLED);
            Predicate fechaInicialPredicate = builder.lessThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localStartDate);

            criteria.where(builder.and(criterioLocation, estatusPredicate, fechaInicialPredicate, criterioActivo));

            conteo = session.createQuery(criteria).getSingleResult();
            transaction.commit();

            logger.info("Abonos vencidos " + conteo);

        } catch (HibernateException e) {
            logger.error("Abono can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addAbonoProyecto() ", e);
            rollback(transaction);
        }

        return conteo;

    }

    public List<AbonoLote> fillAllAbonosVencidos(Date fechaInicial, Location location) {
        Transaction transaction = null;
        List<AbonoLote> result = null;

        try {
            logger.info("Searching all Abonos Vencidos..");
            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);

            LocalDate localStartDate = fechaInicial.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate estatusPredicate = builder.equal(root.get("pagoEstatus"), GenericEnumType.DISABLED);
            Predicate fechaInicialPredicate = builder.lessThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localStartDate);

            criteria.where(builder.and(estatusPredicate, criterioLocation, fechaInicialPredicate, criterioActivo));
            criteria.orderBy(builder.asc(root.get("createdOn")));

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

            logger.info("Total of Abonos Vencidos found: " + (null == result ? -1 : result.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Can not load list of Abonos Vencidos", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fallaAllAbonosVencidos", e);
            rollback(transaction);
        }

        return result;
    }

    public Long contarAbonosAvencerHoy(Date fechaInicial, Location location) {
        logger.info("contarAbonosAvencerHoy");
        Long conteo = 0L;

        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));

            LocalDate localStartDate = fechaInicial.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            //LocalDate localEndDate = fechaFinal.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate estatusPredicate = builder.equal(root.get("pagoEstatus"), GenericEnumType.DISABLED);
            Predicate fechaInicialPredicate = builder.equal(root.get("fechaAPagar").as(LocalDate.class), localStartDate);
            //Predicate fechaFinalPredicate = builder.greaterThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localEndDate);

            criteria.where(builder.and(criterioLocation, estatusPredicate, fechaInicialPredicate, criterioActivo));

            conteo = session.createQuery(criteria).getSingleResult();
            transaction.commit();

            logger.info("Abonos a vencer hoy " + conteo);

        } catch (HibernateException e) {
            logger.error("Abono can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addAbonoProyecto() ", e);
            rollback(transaction);
        }

        return conteo;

    }

    public List<AbonoLote> fillAllAbonosAvencerHoy(Date fechaInicial, Location location) {
        Transaction transaction = null;
        List<AbonoLote> result = null;

        try {
            logger.info("Searching all Abonos A vencer Hoy..");
            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);

            LocalDate localStartDate = fechaInicial.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate estatusPredicate = builder.equal(root.get("pagoEstatus"), GenericEnumType.DISABLED);
            Predicate fechaInicialPredicate = builder.equal(root.get("fechaAPagar").as(LocalDate.class), localStartDate);

            criteria.where(builder.and(criterioLocation, estatusPredicate, fechaInicialPredicate, criterioActivo));
            criteria.orderBy(builder.asc(root.get("createdOn")));

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

            logger.info("Total of Abonos A vencer Hoy found: " + (null == result ? -1 : result.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Can not load list of Abonos A vencer Hoy", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAllAbonosAvencerHoy", e);
            rollback(transaction);
        }

        return result;
    }

    public Long contarAbonosPagadosHoy(Date fechaInicial, Location location) {
        logger.info("contarAbonosPagadosHoy");
        Long conteo = 0L;

        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));

            LocalDate localStartDate = fechaInicial.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            //LocalDate localEndDate = fechaFinal.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate estatusPredicate = builder.equal(root.get("pagoEstatus"), GenericEnumType.ENABLED);
            Predicate fechaInicialPredicate = builder.equal(root.get("lastUpdatedOn").as(LocalDate.class), localStartDate);
            //Predicate fechaFinalPredicate = builder.greaterThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localEndDate);

            criteria.where(builder.and(criterioLocation, estatusPredicate, fechaInicialPredicate, criterioActivo));

            conteo = session.createQuery(criteria).getSingleResult();
            transaction.commit();

            logger.info("Abonos pagados hoy " + conteo);

        } catch (HibernateException e) {
            logger.error("Abono can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addAbonoProyecto() ", e);
            rollback(transaction);
        }

        return conteo;

    }

    public List<AbonoLote> fillAllAbonosPagadosHoy(Date fechaInicial, Location location) {
        Transaction transaction = null;
        List<AbonoLote> result = null;

        try {
            logger.info("Searching all Abonos Pagados Hoy..");
            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);

            LocalDate localStartDate = fechaInicial.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate estatusPredicate = builder.equal(root.get("pagoEstatus"), GenericEnumType.ENABLED);
            Predicate fechaInicialPredicate = builder.equal(root.get("lastUpdatedOn").as(LocalDate.class), localStartDate);

            criteria.where(builder.and(criterioLocation, estatusPredicate, fechaInicialPredicate, criterioActivo));

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

            logger.info("Total of Abonos Pagados Hoy found: " + (null == result ? -1 : result.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Can not load list of Abonos Pagados Hoy", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAllAbonosPagadosHoy", e);
            rollback(transaction);
        }

        return result;
    }

    public List<Lote> buscarLotesPorIdPersona(String idCliente) {
        Transaction transaction = null;
        List<Lote> result = null;

        try {
            logger.info("Searching all Predio..");
            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 criterioCliente = builder.equal(root.get("cliente").get("id"), idCliente);
            criteria.where(builder.and(criterioActivo, criterioCliente));

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

            logger.info("Total of Lote found: " + (null == result ? -1 : result.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Can not load list of Lote", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillLoteDatatable of cliente", e);
            rollback(transaction);
        }

        return result;
    }

    public boolean updateMontoPagado(Lote lote ,User userUpdate) {
        logger.info("updateMontoPagado");

        boolean success = false;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaUpdate<Lote> update = builder.createCriteriaUpdate(Lote.class);
            Root<Lote> rootUpdate = update.from(Lote.class);

            update.set("montoPagado", lote.getMontoPagado());
            update.set("lastUpdatedBy", userUpdate);
            update.set("lastUpdatedOn", new Date());
            update.set("estatusLote", lote.getEstatusLote());
            update.where(builder.equal(rootUpdate.get("id"), lote.getId()));

            int total = session.createQuery(update).executeUpdate();

            if (1 == total) {
                transaction.commit();
                success = true;
                logger.info("Lote " + lote + " updated");
            } else {
                transaction.rollback();
                logger.error("Error Sale updated total: " + total);
            }
        } catch (HibernateException e) {
            logger.error("Lote can not be updated ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method autorizar() ", e);
            rollback(transaction);
        }
        return success;
    }

    public Long contarAbonosDetallePagadosHoy(Date fechaInicial, Location location) {
        logger.info("contarAbonosAndAbonosDetallePagadosHoy");
        Long conteo = 0L;

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

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
            Root<AbonoLoteDetalle> root = criteria.from(AbonoLoteDetalle.class);
            criteria.select(builder.count(root));

            LocalDate localStartDate = fechaInicial.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            Predicate criterioLocation = builder.equal(root.get("abonoLote").get("lote").get("manzana").get("predio").get("location"), location);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);
            Predicate fechaInicialPredicate = builder.equal(root.get("createdOn").as(LocalDate.class), localStartDate);

            criteria.where(builder.and(criterioLocation, fechaInicialPredicate, criterioActivo));

            conteo = session.createQuery(criteria).getSingleResult();
            transaction.commit();

            logger.info("Abonos a vencer hoy " + conteo);

        } catch (HibernateException e) {
            logger.error("Abono can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addAbonoProyecto() ", e);
            rollback(transaction);
        }

        return conteo;
    }

    public List<AbonoLoteView> fillAllAbonosAndAbonosDetallePagadosHoy(Date fechaInicial, Location location) {
        Transaction transaction = null;
        List<AbonoLoteView> result = null;

        try {
            logger.info("Searching all Abonos Pagados Hoy..");
            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 = fechaInicial.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);
            
            Predicate abonoEstatus = builder.equal(root.get("pagoEstatus"), GenericEnumType.ENABLED);
            Predicate tipoAbono = builder.equal(root.get("tipoAbono"), TipoAbono.SUBABONO);
            
            Predicate fechaInicialPredicate = builder.equal(root.get("lastUpdatedOn").as(LocalDate.class), localStartDate);

            criteria.where(builder.and(criterioLocation, fechaInicialPredicate), builder.or(abonoEstatus, tipoAbono));

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

            logger.info("Total of Abonos Pagados Hoy found: " + (null == result ? -1 : result.size()));
            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Can not load list of Abonos Pagados Hoy", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillAllAbonosPagadosHoy", e);
            rollback(transaction);
        }

        return result;
    }

}
