/*
 * 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.predio;

import com.arrebol.taxiservicios.controller.admin.GenericPersonController;
import com.arrebol.taxiservicios.controller.util.HibernateUtil;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.core.ContactNumber;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.enums.PhoneType;
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.FoliosCancelados;
import com.arrebol.taxiservicios.model.predio.Lote;
import com.arrebol.taxiservicios.model.predio.Predio;
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.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 AbonoLoteController extends GenericPersonController implements Serializable {

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

    public boolean addAbonoLote(AbonoLote abonoLote, User user) {
        logger.info("addAbonoLote");
        boolean success;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            abonoLote.setCreatedBy(user);
            abonoLote.setCreatedOn(new Date());
            //System.out.println("Abono Lote can not be added " + abonoLote.getFechaAPagar());
            session.save(abonoLote);

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

    public boolean updateAbonoLote(AbonoLote abonoLote, User user) {
        logger.info("updateAbonoLote");
        boolean success;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            abonoLote.setLastUpdatedBy(user);
            abonoLote.setLastUpdatedOn(new Date());
            session.update(abonoLote);
            transaction.commit();
            success = true;
        } catch (HibernateException e) {
            logger.error("Abono Lote can not be updated ", e);
            success = false;
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method updateAbonoLote() ", e);
            success = false;
            rollback(transaction);
        }
        return success;
    }

    public boolean updateAbonoLote2(AbonoLote abonoLote, User user) {
        logger.info("updateAbonoLote2");
        boolean success;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            session.update(abonoLote);
            transaction.commit();
            success = true;
        } catch (HibernateException e) {
            logger.error("Abono Lote can not be updated ", e);
            success = false;
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method updateAbonoLote2() ", e);
            success = false;
            rollback(transaction);
        }
        return success;
    }

    public boolean deleteAbonoLote(AbonoLote abonoLote) {
        logger.info("deleteAbonoLote");
        boolean success;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            session.delete(abonoLote);
            transaction.commit();
            success = true;
        } catch (HibernateException e) {
            logger.error("Abono Lote could not be delete", e);
            success = false;
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method deleteAbonoLote() ", e);
            success = false;
            rollback(transaction);
        }
        return success;
    }

    public List<AbonoLote> buscarAbonoLotePorRangoFechas(Date startDate, Date endDate, Location location) {
        logger.info("buscarAbonoLotePorRangoFechas");

        List<AbonoLote> results = null;
        Transaction transaction = null;

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

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

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

            // Crear predicados para comparar solo las fechas
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);
            Predicate startDatePredicate = builder.greaterThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localStartDate);
            Predicate endDatePredicate = builder.lessThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localEndDate);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);

            query.where(builder.and(criterioLocation, startDatePredicate, endDatePredicate, criterioActivo));
            query.orderBy(builder.asc(root.get("lastUpdatedOn")));

            results = session.createQuery(query).getResultList();
            transaction.commit();
            logger.info("Total AbonoLote son: " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("No se pudo encontrar los AbonoLote", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method AbonoLote", e);
        }

        return results;
    }

    public List<AbonoLoteDetalle> buscarAbonoLoteDetallePorRangoFechas(Date startDate, Date endDate, Location location) {
        logger.info("buscarAbonoLotePorRangoFechas");

        List<AbonoLoteDetalle> results = null;
        Transaction transaction = null;

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

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

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

            // Crear predicados para comparar solo las fechas
            Predicate criterioLocation = builder.equal(root.get("abonoLote").get("lote").get("manzana").get("predio").get("location"), location);
            Predicate startDatePredicate = builder.greaterThanOrEqualTo(root.get("createdOn").as(LocalDate.class), localStartDate);
            Predicate endDatePredicate = builder.lessThanOrEqualTo(root.get("createdOn").as(LocalDate.class), localEndDate);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);

            query.where(builder.and(criterioLocation, startDatePredicate, endDatePredicate, criterioActivo));
            query.orderBy(builder.asc(root.get("createdOn")));

            results = session.createQuery(query).getResultList();
            transaction.commit();
            logger.info("Total AbonoLote son: " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("No se pudo encontrar los AbonoLote", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method AbonoLote", e);
        }

        return results;
    }

    public List<AbonoLoteView> buscarAbonoLoteViewPorRangoFechas(Date startDate, Date endDate, Location location) {
        logger.info("buscarAbonoLoteViewPorRangoFechas");

        List<AbonoLoteView> results = null;
        Transaction transaction = null;

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

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

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

            // Crear predicados para comparar solo las fechas
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location").get("id"), location.getId());
            Predicate startDatePredicate = builder.greaterThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localStartDate);
            Predicate endDatePredicate = builder.lessThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localEndDate);

            query.where(builder.and(criterioLocation, startDatePredicate, endDatePredicate));

            results = session.createQuery(query).getResultList();
            transaction.commit();
            logger.info("Total AbonoLoteView son: " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("No se pudo encontrar los AbonoLoteView", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method buscarAbonoLoteViewPorRangoFechas", e);
        }

        return results;
    }
    
    public List<AbonoLoteView> buscarAbonoLoteViewPorfechaAPagarRangoFechas(Date startDate, Date endDate, Location location) {
        logger.info("buscarAbonoLoteViewPorfechaAPagarRangoFechas");

        List<AbonoLoteView> results = null;
        Transaction transaction = null;

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

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

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

            // Crear predicados para comparar solo las fechas
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location").get("id"), location.getId());
            Predicate startDatePredicate = builder.greaterThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localStartDate);
            Predicate endDatePredicate = builder.lessThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localEndDate);

            query.where(builder.and(criterioLocation, startDatePredicate, endDatePredicate));

            results = session.createQuery(query).getResultList();
            transaction.commit();
            logger.info("Total AbonoLoteView son: " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("No se pudo encontrar los AbonoLoteView", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method buscarAbonoLoteViewPorfechaAPagarRangoFechas", e);
        }

        return results;
    }

    public List<AbonoLote> buscarAbonoLotePorRangoFechasAndPredio(Date startDate, Date endDate, Location location, String idPredio) {
        logger.info("buscarAbonoLotePorRangoFechas");

        List<AbonoLote> results = null;
        Transaction transaction = null;

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

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

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

            // Crear predicados para comparar solo las fechas
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);
            Predicate criterioPredio = builder.equal(root.get("lote").get("manzana").get("predio").get("id"), idPredio);
            Predicate startDatePredicate = builder.greaterThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localStartDate);
            Predicate endDatePredicate = builder.lessThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localEndDate);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);

            query.where(builder.and(criterioLocation, startDatePredicate, endDatePredicate, criterioActivo, criterioPredio));
            query.orderBy(builder.asc(root.get("lastUpdatedOn")));

            results = session.createQuery(query).getResultList();
            transaction.commit();
            logger.info("Total AbonoLote son: " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("No se pudo encontrar los AbonoLote", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method AbonoLote", e);
        }

        return results;
    }

    public List<AbonoLoteDetalle> buscarAbonoLoteDetallePorRangoFechasAndPredio(Date startDate, Date endDate, Location location, String idPredio) {
        logger.info("buscarAbonoLoteDetallePorRangoFechasAndPredio");

        List<AbonoLoteDetalle> results = null;
        Transaction transaction = null;

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

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

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

            // Crear predicados para comparar solo las fechas
            Predicate criterioLocation = builder.equal(root.get("abonoLote").get("lote").get("manzana").get("predio").get("location"), location);
            Predicate criterioPredio = builder.equal(root.get("abonoLote").get("lote").get("manzana").get("predio").get("id"), idPredio);
            Predicate startDatePredicate = builder.greaterThanOrEqualTo(root.get("createdOn").as(LocalDate.class), localStartDate);
            Predicate endDatePredicate = builder.lessThanOrEqualTo(root.get("createdOn").as(LocalDate.class), localEndDate);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);

            query.where(builder.and(criterioLocation, startDatePredicate, endDatePredicate, criterioActivo, criterioPredio));
            query.orderBy(builder.asc(root.get("createdOn")));

            results = session.createQuery(query).getResultList();
            transaction.commit();
            logger.info("Total AbonoLoteDetalle son: " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("No se pudo encontrar los AbonoLoteDetalle", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method AbonoLoteDetalle", e);
        }

        return results;
    }

    public List<AbonoLoteDetalle> buscarAbonoLoteDetalleByAbonoLote(AbonoLote abono) {
        logger.info("buscarAbonoLoteDetallePorRangoFechasAndPredio");

        List<AbonoLoteDetalle> results = null;
        Transaction transaction = null;

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

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

            // Crear predicados para comparar solo las fechas
            Predicate abonoPredicate = builder.equal(root.get("abonoLote").get("id"), abono.getId());
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);

            query.where(builder.and(criterioActivo, abonoPredicate));
            query.orderBy(builder.asc(root.get("createdOn")));

            results = session.createQuery(query).getResultList();
            transaction.commit();
            logger.info("Total AbonoLoteDetalle son: " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("No se pudo encontrar los AbonoLoteDetalle", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method AbonoLoteDetalle", e);
        }

        return results;
    }

    public List<AbonoLoteView> buscarAbonoLoteViewPorRangoFechasAndPredio(Date startDate, Date endDate, Location location, String idPredio) {
        logger.info("buscarAbonoLoteViewPorRangoFechasAndPredio");

        List<AbonoLoteView> results = null;
        Transaction transaction = null;

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

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

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

            // Crear predicados para comparar solo las fechas
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location").get("id"), location.getId());
            Predicate criterioPredio = builder.equal(root.get("lote").get("manzana").get("predio").get("id"), idPredio);
            Predicate startDatePredicate = builder.greaterThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localStartDate);
            Predicate endDatePredicate = builder.lessThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localEndDate);

            query.where(builder.and(criterioLocation, startDatePredicate, endDatePredicate, criterioPredio));

            results = session.createQuery(query).getResultList();
            transaction.commit();
            logger.info("Total AbonoLoteView son: " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("No se pudo encontrar los AbonoLoteView", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method buscarAbonoLoteViewPorRangoFechasAndPredio", e);
        }

        return results;
    }
    
        public List<AbonoLoteView> buscarAbonoLoteViewPorfechaAPagarRangoFechasAndPredio(Date startDate, Date endDate, Location location, String idPredio) {
        logger.info("buscarAbonoLoteViewPorfechaAPagarRangoFechasAndPredio");

        List<AbonoLoteView> results = null;
        Transaction transaction = null;

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

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

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

            // Crear predicados para comparar solo las fechas
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location").get("id"), location.getId());
            Predicate criterioPredio = builder.equal(root.get("lote").get("manzana").get("predio").get("id"), idPredio);
            Predicate startDatePredicate = builder.greaterThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localStartDate);
            Predicate endDatePredicate = builder.lessThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localEndDate);

            query.where(builder.and(criterioLocation, startDatePredicate, endDatePredicate, criterioPredio));

            results = session.createQuery(query).getResultList();
            transaction.commit();
            logger.info("Total AbonoLoteView son: " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("No se pudo encontrar los AbonoLoteView", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method buscarAbonoLoteViewPorfechaAPagarRangoFechasAndPredio", e);
        }

        return results;
    }

    public List<AbonoLote> buscarAbonoLoteForEstatusPagoAndLocationAndPredio(GenericEnumType estatusPago, Location location, String idPredio) {
        logger.info("buscarAbonoLotePorRangoFechas");

        List<AbonoLote> results = null;
        Transaction transaction = null;

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

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

            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);
            Predicate criterioPredio = builder.equal(root.get("lote").get("manzana").get("predio").get("id"), idPredio);
            Predicate criterioPagoEstatus = builder.equal(root.get("pagoEstatus"), estatusPago);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);

            query.where(builder.and(criterioPagoEstatus, criterioLocation, criterioPredio, criterioActivo));
            query.orderBy(builder.asc(root.get("fechaAPagar")));

            results = session.createQuery(query).getResultList();
            transaction.commit();
            logger.info("Total AbonoLote son: " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("No se pudo encontrar los AbonoLote", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method AbonoLote", e);
        }

        return results;
    }

    public List<AbonoLote> buscarAbonoLotePagadosPorRangoFechasAndPredio(GenericEnumType estatusPago, Date startDate, Date endDate, Location location, String idPredio) {
        logger.info("buscarAbonoLotePorRangoFechas");

        List<AbonoLote> results = null;
        Transaction transaction = null;

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

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

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

            // Crear predicados para comparar solo las fechas
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);
            Predicate criterioPredio = builder.equal(root.get("lote").get("manzana").get("predio").get("id"), idPredio);
            Predicate startDatePredicate = builder.greaterThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localStartDate);
            Predicate endDatePredicate = builder.lessThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localEndDate);
            Predicate criterioPagoEstatus = builder.equal(root.get("pagoEstatus"), estatusPago);
            Predicate criterioActivo = builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED);

            query.where(builder.and(criterioPagoEstatus, criterioLocation, startDatePredicate, endDatePredicate, criterioActivo, criterioPredio));
            query.orderBy(builder.asc(root.get("lastUpdatedOn")));

            results = session.createQuery(query).getResultList();
            transaction.commit();
            logger.info("Total AbonoLote son: " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("No se pudo encontrar los AbonoLote", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method AbonoLote", e);
        }

        return results;
    }
    
        public List<AbonoLoteView> buscarAbonoLoteViewPagadosPorRangoFechasAndPredio(GenericEnumType estatusPago, Date startDate, Date endDate, Location location, String idPredio) {
        logger.info("buscarAbonoLoteViewPagadosPorRangoFechasAndPredio");

        List<AbonoLoteView> results = null;
        Transaction transaction = null;

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

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

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

            // Crear predicados para comparar solo las fechas
            Predicate criterioLocation = builder.equal(root.get("lote").get("manzana").get("predio").get("location"), location);
            Predicate criterioPredio = builder.equal(root.get("lote").get("manzana").get("predio").get("id"), idPredio);
            Predicate startDatePredicate = builder.greaterThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localStartDate);
            Predicate endDatePredicate = builder.lessThanOrEqualTo(root.get("lastUpdatedOn").as(LocalDate.class), localEndDate);
            Predicate criterioPagoEstatus = builder.equal(root.get("pagoEstatus"), estatusPago);

            query.where(builder.and(criterioPagoEstatus, criterioLocation, startDatePredicate, endDatePredicate, criterioPredio));

            results = session.createQuery(query).getResultList();
            transaction.commit();
            logger.info("Total AbonoLoteView son: " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("No se pudo encontrar los AbonoLoteView", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method AbonoLoteView", e);
        }

        return results;
    }

    public ContactNumber finPhoneByClient(String idCliente) {
        logger.info("finPhoneByClient");

        ContactNumber result = null;
        Transaction transaction = null;

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

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

            Predicate criterio = (builder.equal(root.get("person").get("id"), idCliente));
            Predicate criterio2 = (builder.equal(root.get("phoneType"), PhoneType.MOBILE));
            Predicate criterio3 = builder.equal(root.get("preferenced"), 1);
            criteria.where(builder.and(criterio, criterio2, criterio3));

            result = session.createQuery(criteria).getSingleResult();
            transaction.commit();
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("No se encontro el Contact Number ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method finPhoneByClient Contact Number: ", e);
        }

        return result;
    }

    public List<AbonoLote> fillAbonoLoteByLoteAndTipoAbono(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 criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
            Predicate criterio3 = (builder.equal(root.get("tipoAbono"), tipo));
            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> fillAbonoLoteByLoteAndTipoAbonoAndEstatus(Lote lote, TipoAbono tipo, GenericEnumType estatus) {
        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"), estatus));
            Predicate criterio4 = (builder.equal(root.get("tipoAbono"), tipo));
            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<FoliosCancelados> fillFoliosCanceladosByPredio(String idPredio) {
        logger.info("fillFoliosCanceladosBy");

        List<FoliosCancelados> results = null;
        Transaction transaction = null;

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

            CriteriaQuery<FoliosCancelados> query = builder.createQuery(FoliosCancelados.class);
            Root<FoliosCancelados> root = query.from(FoliosCancelados.class);

            // Crear predicados para comparar solo las fechas
           Predicate criterio = (builder.equal(root.get("predio").get("id"), idPredio));     

            query.where(builder.and(criterio));
            query.orderBy(builder.desc(root.get("fechaEliminacion")));

            results = session.createQuery(query).getResultList();
            transaction.commit();
            logger.info("Total de folios cancelados encontrados : " + results.size());
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Ocurrió un error al tratar de cargar el historiala de folios cancelados: ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("fillFoliosCanceladosBy() ", e);
        }

        return results;
    }

}
