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

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.User;
import com.arrebol.taxiservicios.model.enums.EstatusTour;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.tours.DetallesPagoEspacios;
import com.arrebol.taxiservicios.model.tours.EspaciosTour;
import com.arrebol.taxiservicios.model.tours.EspaciosTourView;
import com.arrebol.taxiservicios.model.tours.HistorialAbonoMultipleTours;
import com.arrebol.taxiservicios.model.tours.PagosEspacioTour;
import com.arrebol.taxiservicios.model.tours.PagosEspaciosTourDetalle;
import com.arrebol.taxiservicios.model.tours.PagosEspaciosTourView;
import com.arrebol.taxiservicios.model.tours.Tours;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
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 Crov
 */
public class ToursController extends GenericPersonController implements Serializable {

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

   public boolean addTour(Tours tour, User user, boolean save) {
      logger.info("addCabina");
      boolean success = false;
      Transaction transaction = null;

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

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

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

   public List<Tours> fillToursByLocation(Location location) {
      logger.info("fillToursByLocation");
      List<Tours> resultList = null;
      Transaction transaction = null;
      try {
         logger.info("Searching for tours..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

         Predicate criterio = (builder.equal(root.get("location"), location));
         Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
         criteria.where(builder.and(criterio, criterio2));
         criteria.orderBy(builder.desc(root.get("createdOn")));
         criteria.orderBy(builder.asc(root.get("estatus")));
         resultList = session.createQuery(criteria).getResultList();

         logger.info("Total off tours productos found: " + (null == resultList ? -1 : resultList.size()));
         transaction.commit();
      } catch (HibernateException e) {
         logger.error("Tours cannot be loaded" + e);
         rollback(transaction);
      } catch (Exception e) {
         logger.error("Method fillToursByLocation(): " + e);
         rollback(transaction);
      }
      return resultList;
   }

   public boolean addEspaciosTour(EspaciosTour espacio, User user, boolean save) {
      logger.info("addEspaciosTour");
      boolean success = false;
      Transaction transaction = null;

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

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

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

   public boolean addDetallesPagoEspacios(DetallesPagoEspacios detalleEspacio, User user, boolean save) {
      logger.info("addDetallesPagoEspacios");
      boolean success = false;
      Transaction transaction = null;

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

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

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

   public List<EspaciosTour> fillEspaciosTourByTour(Tours tour) {
      logger.info("fillEspaciosTourByTour");
      List<EspaciosTour> resultList = null;
      Transaction transaction = null;
      try {
         logger.info("Searching espacio for tours..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

         Predicate criterio = (builder.equal(root.get("tour"), tour));
         Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
         criteria.where(builder.and(criterio, criterio2));
         criteria.orderBy(builder.asc(root.get("consecutivo")));
         resultList = session.createQuery(criteria).getResultList();

         logger.info("Total off espacio found: " + (null == resultList ? -1 : resultList.size()));
         transaction.commit();
      } catch (HibernateException e) {
         logger.error("Rspacio tour cannot be loaded" + e);
         rollback(transaction);
      } catch (Exception e) {
         logger.error("Method fillEspaciosTourByTour(): " + e);
         rollback(transaction);
      }
      return resultList;
   }

   public List<EspaciosTour> fillEspaciosTourByDetallesPagoEspacios(DetallesPagoEspacios detalle) {
      logger.info("fillEspaciosTourByDetallesPagoEspacios");
      List<EspaciosTour> resultList = null;
      Transaction transaction = null;
      try {
         logger.info("Searching espacio for tours..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

         Predicate criterio = (builder.equal(root.get("detallesPagoEspacios").get("id"), detalle.getId()));
         Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
         Predicate criterio3 = (builder.equal(root.get("espacioClientePago"), false));
         criteria.where(builder.and(criterio, criterio2, criterio3));
         criteria.orderBy(builder.asc(root.get("consecutivo")));
         resultList = session.createQuery(criteria).getResultList();

         logger.info("Total off espacio found: " + (null == resultList ? -1 : resultList.size()));
         transaction.commit();
      } catch (HibernateException e) {
         logger.error("Rspacio tour cannot be loaded" + e);
         rollback(transaction);
      } catch (Exception e) {
         logger.error("Method fillEspaciosTourByDetallesPagoEspacios(): " + e);
         rollback(transaction);
      }
      return resultList;
   }

   public List<EspaciosTour> fillEspaciosTourByTourDisponibles(Tours tour) {
      logger.info("fillEspaciosTourByTourDisponibles");
      List<EspaciosTour> resultList = null;
      Transaction transaction = null;
      try {
         logger.info("Searching espacio for tours..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

         Predicate criterio = (builder.equal(root.get("tour"), tour));
         Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
         Predicate criterio3 = (builder.equal(root.get("estatusEspacio"), GenericEnumType.DISABLED));
         criteria.where(builder.and(criterio, criterio2, criterio3));
         criteria.orderBy(builder.asc(root.get("consecutivo")));
         resultList = session.createQuery(criteria).getResultList();

         logger.info("Total off espacio found: " + (null == resultList ? -1 : resultList.size()));
         transaction.commit();
      } catch (HibernateException e) {
         logger.error("Rspacio tour cannot be loaded" + e);
         rollback(transaction);
      } catch (Exception e) {
         logger.error("Method fillEspaciosTourByTourDisponibles(): " + e);
         rollback(transaction);
      }
      return resultList;
   }

   public boolean addPagosEspacioTour(PagosEspacioTour pago, User user, boolean save) {
      logger.info("addPagosEspacioTour");
      boolean success = false;
      Transaction transaction = null;

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

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

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

   public List<PagosEspacioTour> fillPagosEspacioTourByDetalleEspaciosTour(DetallesPagoEspacios detalle) {
      logger.info("fillPagosEspacioTourByDetalleEspaciosTour");
      List<PagosEspacioTour> resultList = null;
      Transaction transaction = null;
      try {
         logger.info("Searching pago espacio for espacios tour..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

         Predicate criterio = (builder.equal(root.get("detallesPagoEspacios"), detalle));
         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 off pago found: " + (null == resultList ? -1 : resultList.size()));
         transaction.commit();
      } catch (HibernateException e) {
         logger.error("Pagos cannot be loaded" + e);
         rollback(transaction);
      } catch (Exception e) {
         logger.error("Method fillPagosEspacioTourByDetalleEspaciosTour(): " + e);
         rollback(transaction);
      }
      return resultList;
   }

   public List<PagosEspacioTour> fillPagosEspacioTourByDetalleEspaciosTourAndEstus(DetallesPagoEspacios detalle, GenericEnumType estatus) {
      logger.info("fillPagosEspacioTourByDetalleEspaciosTour");
      List<PagosEspacioTour> resultList = null;
      Transaction transaction = null;
      try {
         logger.info("Searching pago espacio for espacios tour..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

         Predicate criterio = (builder.equal(root.get("detallesPagoEspacios"), detalle));
         Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
         Predicate criterio3 = (builder.equal(root.get("pagoEstatus"), estatus));
         criteria.where(builder.and(criterio, criterio2, criterio3));
         criteria.orderBy(builder.asc(root.get("fechaAPagar")));
         resultList = session.createQuery(criteria).getResultList();

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

   public List<PagosEspacioTour> fillPagosEspacioTourNoPagafosByDetalle(DetallesPagoEspacios detalle) {
      logger.info("fillPagosEspacioTourNoPagafosByDetalle");
      List<PagosEspacioTour> resultList = null;
      Transaction transaction = null;
      try {
         logger.info("Searching ventas for pagos..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

         Predicate criterio = (builder.equal(root.get("detallesPagoEspacios"), detalle));
         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 off Ventas found: " + (null == resultList ? -1 : resultList.size()));
         transaction.commit();
      } catch (HibernateException e) {
         logger.error("Ventas cannot be loaded " + e);
         rollback(transaction);
      } catch (Exception e) {
         logger.error("Method fillPagosEspacioTourNoPagafosByDetalle() " + e);
         rollback(transaction);
      }
      return resultList;
   }

   public List<PagosEspacioTour> fillPagosEspacioTourNoPagadosByLocation(Location location) {
      logger.info("fillPagosEspacioTourNoPagadosByLocation");
      List<PagosEspacioTour> resultList = null;
      Transaction transaction = null;
      try {
         logger.info("Searching pago espacio for espacios tour..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

         Predicate criterio = (builder.equal(root.get("detallesPagoEspacios").get("tour").get("location"), location));
         Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
         Predicate criterio3 = (builder.equal(root.get("pagoEstatus"), GenericEnumType.DISABLED));
         criteria.where(builder.and(criterio, criterio2, criterio3));
         criteria.orderBy(builder.asc(root.get("fechaAPagar")));
         resultList = session.createQuery(criteria).getResultList();

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

   public List<PagosEspacioTour> fillPagosEspacioTourNoPagadosByLocationAndFechas(Location location, Date fechaInicial, Date fechaFinal) {
      logger.info("fillPagosEspacioTourNoPagadosByLocation");
      List<PagosEspacioTour> resultList = null;
      Transaction transaction = null;
      try {
         logger.info("Searching pago espacio for espacios tour..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

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

         Predicate criterio = (builder.equal(root.get("detallesPagoEspacios").get("tour").get("location"), location));
         Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
         Predicate criterio3 = (builder.equal(root.get("pagoEstatus"), GenericEnumType.DISABLED));

         Predicate criterio4 = (builder.greaterThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localStartDate));
         Predicate criterio5 = (builder.lessThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localEndDate));

         criteria.where(builder.and(criterio, criterio2, criterio3, criterio4, criterio5));
         criteria.orderBy(builder.asc(root.get("fechaAPagar")));
         resultList = session.createQuery(criteria).getResultList();

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

   public List<PagosEspacioTour> fillPagosFuturosEspacioTourNoPagadosByLocationAndFechas(Location location, Date fechaInicial) {
      logger.info("fillPagosEspacioTourNoPagadosByLocation");
      List<PagosEspacioTour> resultList = null;
      Transaction transaction = null;
      try {
         logger.info("Searching pago espacio for espacios tour..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

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

         Predicate criterio = (builder.equal(root.get("detallesPagoEspacios").get("tour").get("location"), location));
         Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
         Predicate criterio3 = (builder.equal(root.get("pagoEstatus"), GenericEnumType.DISABLED));

         Predicate criterio4 = (builder.greaterThanOrEqualTo(root.get("fechaAPagar").as(LocalDate.class), localStartDate));

         criteria.where(builder.and(criterio, criterio2, criterio3, criterio4));
         criteria.orderBy(builder.asc(root.get("fechaAPagar")));
         resultList = session.createQuery(criteria).getResultList();

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

   public List<Tours> fillToursActivosByLocationAndFechas(Location location, Date fechaInicial) {
      logger.info("fillToursActivosByLocationAndFechas");
      List<Tours> resultList = null;
      Transaction transaction = null;
      try {
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

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

         Predicate criterio = (builder.equal(root.get("location"), location));
         Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
         Predicate criterio3 = (builder.equal(root.get("estatus"), EstatusTour.CURSO));

         Predicate criterio4 = (builder.greaterThanOrEqualTo(root.get("fechaInicio").as(LocalDate.class), localStartDate));

         criteria.where(builder.and(criterio, criterio2, criterio3, criterio4));
         criteria.orderBy(builder.asc(root.get("fechaInicio")));
         resultList = session.createQuery(criteria).getResultList();

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

   public List<Tours> fillToursActivosByLocationAndFechas(Location location, Date fechaInicial, Date fechaFinal) {
      logger.info("fillToursActivosByLocationAndFechas");
      List<Tours> resultList = null;
      Transaction transaction = null;
      try {
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

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

         Predicate criterio = (builder.equal(root.get("location"), location));
         Predicate criterio2 = (builder.equal(root.get("estatusActivo"), GenericEnumType.ENABLED));
         Predicate criterio3 = (builder.equal(root.get("estatus"), EstatusTour.CURSO));

         Predicate criterio4 = (builder.greaterThanOrEqualTo(root.get("fechaInicio").as(LocalDate.class), localStartDate));
         Predicate criterio5 = (builder.lessThanOrEqualTo(root.get("fechaInicio").as(LocalDate.class), localEndDate));

         criteria.where(builder.and(criterio, criterio2, criterio3, criterio4, criterio5));
         criteria.orderBy(builder.asc(root.get("fechaInicio")));
         resultList = session.createQuery(criteria).getResultList();

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

   public boolean addPagosEspaciosTourDetalle(PagosEspaciosTourDetalle pago, User user, boolean save) {
      logger.info("addPagosEspaciosTourDetalle");
      boolean success = false;
      Transaction transaction = null;

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

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

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

   public List<PagosEspaciosTourDetalle> fillPagosEspaciosTourDetalleByPagosEspacioTour(PagosEspacioTour pagoEspacio) {
      logger.info("fillPagosEspaciosTourDetalleByPagosEspacioTour");
      List<PagosEspaciosTourDetalle> resultList = null;
      Transaction transaction = null;
      try {
         logger.info("Searching pago espacio detalle for pago espacio..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

         Predicate criterio = (builder.equal(root.get("pagosEspacioTour"), pagoEspacio));
         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 off detalles found: " + (null == resultList ? -1 : resultList.size()));
         transaction.commit();
      } catch (HibernateException e) {
         logger.error("Detalles cannot be loaded" + e);
         rollback(transaction);
      } catch (Exception e) {
         logger.error("Method fillPagosEspaciosTourDetalleByPagosEspacioTour(): " + e);
         rollback(transaction);
      }
      return resultList;
   }

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

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

         if (save) {
            abonoMultiple.setId(UUID.randomUUID().toString());
            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 addHitorialAbonoMultipleTours() ", e);
         rollback(transaction);
      }
      return success;
   }

   public PagosEspaciosTourView fillFoliosByPagos(String abreviacionFolio) {
      PagosEspaciosTourView result = null;
      Transaction transaction = null;
      try {
         logger.info("Search last generated folio..");

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

         String query = "SELECT pa FROM PagosEspaciosTourView pa "
                 + "WHERE pa.folio LIKE '" + abreviacionFolio + "%' "
                 + "ORDER BY "
                 + "SUBSTRING_INDEX(pa.folio, '-', 1) DESC, "
                 + "SUBSTRING_INDEX(SUBSTRING_INDEX(pa.folio, '-', -1), '-', -6) DESC ";

         result = (PagosEspaciosTourView) session.createQuery(query)
                 .setMaxResults(1)
                 .uniqueResult();

         transaction.commit();
      } catch (HibernateException e) {
         logger.error("Search for the last generated folio " + e);
         rollback(transaction);
      } catch (Exception e) {
         logger.error("Method fillFoliosByPagos() " + e);
         rollback(transaction);
      }
      return result;
   }

   public List<Tours> getlistToursByCliente(String idCliente) {
      logger.info("getlistToursByCliente");
      List<Tours> list = new ArrayList<>();

      Transaction transaction = null;

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

         String query = "SELECT distinct tor FROM Tours tor\n"
                 + "inner join EspaciosTour es on tor.id=es.tour\n"
                 + "where es.clientePago.id = '" + idCliente + "'\n"
                 + "and es.estatusActivo='ENABLED' AND tor.estatusActivo='ENABLED'\n"
                 + "order by tor.createdOn desc";

         list = session.createQuery(query).getResultList();

         transaction.commit();
         logger.info("Driver's list " + list);
      } catch (HibernateException e) {
         logger.error("Can not load all tours ", e);
         rollback(transaction);
      } catch (Exception e) {
         logger.error("Method getlistToursByCliente() ", e);
         rollback(transaction);
      }
      return list;
   }

   public Tours fillToursById(String id) {
      logger.info("fillToursById");
      Tours result = null;
      Transaction transaction = null;
      try {
         logger.info("Searching AbonoMultiple..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

         CriteriaQuery<Tours> criteria = builder.createQuery(Tours.class);
         Root<Tours> root = criteria.from(Tours.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("Tours " + e);
         rollback(transaction);
      } catch (Exception e) {
         logger.error("Method fillToursById() " + e);
         rollback(transaction);
      }
      return result;
   }

   public DetallesPagoEspacios fillDetallesPagoEspaciosById(String id) {
      logger.info("fillDetallesPagoEspaciosById");
      DetallesPagoEspacios result = null;
      Transaction transaction = null;
      try {
         logger.info("Searching DetallesPagoEspacios..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

         CriteriaQuery<DetallesPagoEspacios> criteria = builder.createQuery(DetallesPagoEspacios.class);
         Root<DetallesPagoEspacios> root = criteria.from(DetallesPagoEspacios.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("Tours " + e);
         rollback(transaction);
      } catch (Exception e) {
         logger.error("Method fillDetallesPagoEspaciosById() " + e);
         rollback(transaction);
      }
      return result;
   }

   public List<EspaciosTourView> fillEspaciosTourView(String idTour) {
      logger.info("fillEspaciosTourView");
      List<EspaciosTourView> resultList = null;
      Transaction transaction = null;
      try {
         logger.info("Searching for tours..");
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
         transaction = session.beginTransaction();
         CriteriaBuilder builder = session.getCriteriaBuilder();

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

         Predicate criterio = (builder.equal(root.get("idTour"), idTour));
         criteria.where(builder.and(criterio));
         resultList = session.createQuery(criteria).getResultList();

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

}
