package com.arrebol.taxiservicios.controller.admin;

import com.arrebol.taxiservicios.controller.connection.ConnectionManager;
import com.arrebol.taxiservicios.controller.util.DateWrapper;
import com.arrebol.taxiservicios.controller.util.HibernateUtil;
import com.arrebol.taxiservicios.model.admin.Document;
import com.arrebol.taxiservicios.model.admin.ReleaseResource;
import com.arrebol.taxiservicios.model.admin.Service;
import com.arrebol.taxiservicios.model.catalog.Holiday;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.catalog.RegimenFiscal;
import com.arrebol.taxiservicios.model.core.Address;
import com.arrebol.taxiservicios.model.core.ContactNumber;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.core.PersonCommercialInvoice;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.dashboard.ToCollect;
import com.arrebol.taxiservicios.model.enums.DocumentType;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.enums.PersonType;
import com.arrebol.taxiservicios.model.enums.PhoneType;
import java.io.Serializable;
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.CriteriaDelete;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate;
import javax.persistence.criteria.Path;
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 abstract class GenericPersonController extends ConnectionManager implements Serializable {

    /**
     * Get all person by person type.
     *
     * @param personType Employee, Client, Provider or Driver.
     * @param employeeId Exclude logged user in system for list.
     *
     * @return A list of Employee, Client, Provider or Driver. If is Employee
     * list the current logged user will exclude from list.
     */
    public List<Person> getAllPersonByType(PersonType personType, String employeeId) {
        log.info("Start getAllPersonByType");

        Transaction transaction = null;
        List<Person> clients = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
            Root<Person> root = criteria.from(Person.class);

            Path<String> idPath = root.get("id");
            Path<String> firstNamePath = root.get("firstName");
            Path<String> secondNamePath = root.get("secondName");
            Path<String> lastNamePath = root.get("lastName");
            Path<String> middleNamePath = root.get("middleName");
            Path<Boolean> rootPath = root.get("root");

            criteria.select(builder.construct(Person.class,
                    idPath, firstNamePath, secondNamePath, lastNamePath, middleNamePath, rootPath));

            criteria.where(
                    builder.and(
                            builder.equal(root.get("active"), true),
                            builder.equal(root.get("root"), false),
                            builder.equal(root.get("personType"), personType)
                    )
            );

            criteria.orderBy(
                    builder.asc(root.get("lastName")),
                    builder.asc(root.get("middleName")),
                    builder.asc(root.get("firstName"))
            );

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

            transaction.commit();
            log.info("Persons " + personType + " succefully loaded, size: " + clients.size());
        } catch (HibernateException e) {
            log.error("Person " + personType + "  can not be loaded ", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method getAllPersonByType( " + personType + " ) ", e);
            rollback(transaction);
        }
        return clients;
    }

    /**
     *
     * @param personType
     * @return
     */
    public List<Person> getAllPersonsByPersonTye(PersonType personType) {
        log.info("Start getAllPersonByType");

        Transaction transaction = null;
        List<Person> persons = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
            Root<Person> root = criteria.from(Person.class);

            criteria.select(root);

            criteria.where(
                    builder.and(
                            builder.equal(root.get("active"), true),
                            builder.equal(root.get("root"), false),
                            builder.equal(root.get("personType"), personType)
                    )
            );

            criteria.orderBy(
                    builder.asc(root.get("lastName")),
                    builder.asc(root.get("middleName")),
                    builder.asc(root.get("firstName"))
            );

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

            transaction.commit();
            log.info("Persons " + personType + " succefully loaded, size: " + persons.size());
        } catch (HibernateException e) {
            log.error("Person " + personType + "  can not be loaded ", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method getAllPersonByType( " + personType + " ) ", e);
            rollback(transaction);
        }
        return persons;
    }
    
    /**
     *
     * @param mail
     * @return
     */
    public List<Person> getAllPersonsByMail(String mail) {
        log.info("Start getAllPersonByType");

        Transaction transaction = null;
        List<Person> persons = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
            Root<Person> root = criteria.from(Person.class);

            criteria.select(root);

            criteria.where(
                    builder.and(
                            builder.equal(root.get("active"), true),
                            builder.equal(root.get("root"), false),
                            builder.equal(root.get("mail"), mail)
                    )
            );

            criteria.orderBy(
                    builder.asc(root.get("lastName")),
                    builder.asc(root.get("middleName")),
                    builder.asc(root.get("firstName"))
            );

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

            transaction.commit();
            log.info("Persons " + mail + " succefully loaded, size: " + persons.size());
        } catch (HibernateException e) {
            log.error("Person " + mail + "  can not be loaded ", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method getAllPersonsByMail( " + mail + " ) ", e);
            rollback(transaction);
        }
        return persons;
    }
    
     public List<Person> getAllPersonsByPersonTye2(PersonType personType) {
        log.info("Start getAllPersonByType");

        Transaction transaction = null;
        List<Person> persons = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
            Root<Person> root = criteria.from(Person.class);

            criteria.select(root);

            criteria.where(
                    builder.and(
                            builder.equal(root.get("personType"), personType)
                    )
            );

            criteria.orderBy(
                    builder.asc(root.get("lastName")),
                    builder.asc(root.get("middleName")),
                    builder.asc(root.get("firstName"))
            );

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

            transaction.commit();
            log.info("Persons " + personType + " succefully loaded, size: " + persons.size());
        } catch (HibernateException e) {
            log.error("Person " + personType + "  can not be loaded ", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method getAllPersonByType( " + personType + " ) ", e);
            rollback(transaction);
        }
        return persons;
    }

    public List<Person> getAllPersonsPoolByPersonTye(PersonType personType) {
        log.info("Start getAllPersonsPoolByPersonTye");

        Transaction transaction = null;
        List<Person> persons = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
            Root<Person> root = criteria.from(Person.class);

            criteria.select(root);

            criteria.where(
                    builder.and(
                            builder.equal(root.get("active"), false),
                            builder.equal(root.get("root"), false),
                            builder.equal(root.get("personType"), personType),
                            builder.and(
                                    builder.or(
                                            builder.equal(root.get("blackList"), GenericEnumType.DISABLED),
                                            builder.isNull(root.get("blackList"))
                                    )
                            )
                    )
            );

            criteria.orderBy(
                    builder.asc(root.get("lastName")),
                    builder.asc(root.get("middleName")),
                    builder.asc(root.get("firstName"))
            );

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

            transaction.commit();
            log.info("Persons pool" + personType + " succefully loaded, size: " + persons.size());
        } catch (HibernateException e) {
            log.error("Person pool " + personType + "  can not be loaded ", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method getAllPersonsPoolByPersonTye( " + personType + " ) ", e);
            rollback(transaction);
        }
        return persons;
    }

    public List<Person> getAllPersonsBlackListByPersonTye(PersonType personType) {
        log.info("Start getAllPersonsBlackListByPersonTye");

        Transaction transaction = null;
        List<Person> persons = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
            Root<Person> root = criteria.from(Person.class);

            criteria.select(root);

            criteria.where(
                    builder.and(
                            builder.equal(root.get("active"), false),
                            builder.equal(root.get("root"), false),
                            builder.equal(root.get("personType"), personType),
                            builder.and(
                                    builder.or(
                                            builder.equal(root.get("blackList"), GenericEnumType.ENABLED),
                                            builder.isNotNull(root.get("blackList"))
                                    )
                            )
                    )
            );

            criteria.orderBy(
                    builder.asc(root.get("lastName")),
                    builder.asc(root.get("middleName")),
                    builder.asc(root.get("firstName"))
            );

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

            transaction.commit();
            log.info("Persons blacklist" + personType + " succefully loaded, size: " + persons.size());
        } catch (HibernateException e) {
            log.error("Person blacklist " + personType + "  can not be loaded ", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method getAllPersonsBlackListByPersonTye( " + personType + " ) ", e);
            rollback(transaction);
        }
        return persons;
    }

    /**
     * Get person by id, bring Employee/Customer/Provider/Driver, Contact
     * Numbers and Address details.
     *
     * @param personId ID to find.
     *
     * @return Person (Employee/Customer/Provider/Driver), contact number and
     * address details.
     */
    public Person getPersonById(String personId) {
        log.info("getPersonById");

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

            employee = session.get(Person.class, personId);

            transaction.commit();
            log.info("Person " + employee);
        } catch (HibernateException e) {
            log.error("Person cannot be loaded " + personId, e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method getPersonById(" + personId + ") ", e);
            rollback(transaction);
        }
        return employee;
    }
    
    public PersonCommercialInvoice getPersonCommercialInvoiceById(String personId) {
        log.info("getPersonById");

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

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

      
            criteria.where(builder.equal(root.get("idPerson"), personId));
            
            employee = session.createQuery(criteria).uniqueResult();
            transaction.commit();
            
            
            log.info("Person " + employee);
        } catch (HibernateException e) {
            log.error("Person cannot be loaded " + personId, e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method getPersonById(" + personId + ") ", e);
            rollback(transaction);
        }
        return employee;
    }

    /**
     * Save/Update an employee in the system.
     *
     * @param person Person to be saved (Employee/Customer/Provider/Driver).
     * @param userName User to load and use to set createBy/updateBy user in the
     * record.
     * @param save true save otherwise update.
     *
     * @return True if Person was saved/updated otherwise false.
     */
    public boolean addPerson(Person person, String userName, boolean save) {
        log.info("addPerson");

        boolean success = false;

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

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<User> criteria = builder.createQuery(User.class);
            Root<User> root = criteria.from(User.class);
            Path<String> idPath = root.get("id");
            Path<String> userNamePath = root.get("userName");

            criteria.select(builder.construct(User.class, idPath, userNamePath));
            criteria.where(builder.equal(root.get("userName"), userName));
            User user = session.createQuery(criteria).uniqueResult();

            if (save) {
                person.setCreatedBy(user);
                person.setUsuarioApp(GenericEnumType.DISABLED);
                session.save(person);
                transaction.commit();

                Date date = DateWrapper.getTodayMXTime();
                ReleaseResourceController releaseResourceController = new ReleaseResourceController();
                ReleaseResource releaseResource = new ReleaseResource(UUID.randomUUID().toString(), person, date, GenericEnumType.ENABLED, user, date);
                
                releaseResourceController.saveReleaseResource(releaseResource);
                log.info("Person saved " + person.getId());
            } else {
                person.setLastUpdatedBy(user);
                session.update(person);
                transaction.commit();
                log.info("Person updated " + person.getId());
            }

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

    /**
     * Do a logical delete from an person in the system
     *
     * @param personId
     * @param userName
     * @return True if employee was logical deleted otherwise false.
     */
    public boolean deletePersonById(String personId, String userName) {
        log.info("deletePersonById");

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

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<User> criteria = builder.createQuery(User.class);
            Root<User> root = criteria.from(User.class);
            Path<String> idPath = root.get("id");
            Path<String> userNamePath = root.get("userName");

            criteria.select(builder.construct(User.class, idPath, userNamePath));
            criteria.where(builder.equal(root.get("userName"), userName));
            User user = session.createQuery(criteria).uniqueResult();

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

            update.set("active", false);
            update.set("lastUpdatedBy", user);
            update.set("lastUpdatedOn", new Date());
            update.where(builder.equal(rootUpdate.get("id"), personId));

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

            if (1 == total) {
                transaction.commit();
                success = true;
                log.info("Person " + personId + " deleted");
            } else {
                transaction.rollback();
                log.error("Error Person deleted total: " + total);
            }
        } catch (HibernateException e) {
            log.error("Person can not be deleted ", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method deletePersonById() ", e);
            rollback(transaction);
        }
        return success;
    }
    
    public boolean CreateUserPersonById(String personId,String password, User user) {
        log.info("deletePersonById");

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

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

            
            update.set("usuarioApp", GenericEnumType.ENABLED);
            update.set("password", password);
            update.set("lastUpdatedBy", user);
            update.set("lastUpdatedOn", new Date());
            update.where(builder.equal(rootUpdate.get("id"), personId));

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

            if (1 == total) {
                transaction.commit();
                success = true;
                log.info("Person " + personId + " deleted");
            } else {
                transaction.rollback();
                log.error("Error Person deleted total: " + total);
            }
        } catch (HibernateException e) {
            log.error("Person can not be deleted ", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method deletePersonById() ", e);
            rollback(transaction);
        }
        return success;
    }

    /**
     * Save Person details.
     *
     * @param firstName
     * @param secondName
     * @param lastName
     * @param middleName
     * @param birthdate
     * @param personId
     * @param userId
     * @param payment
     *
     * @return True if person details were updated otherwise false.
     */
    public boolean updatePersonById(String firstName, String secondName,
            String lastName, String middleName, Date birthdate,
            String personId, String userId, Float payment, String locationId) {
        log.info("updateEmployeeById");

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

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

            if (null != payment) {
                update.set("payment", payment);
            }
            update.set("firstName", firstName);
            update.set("secondName", secondName);
            update.set("lastName", lastName);
            update.set("middleName", middleName);
            update.set("birthdate", birthdate);
            update.set("lastUpdatedBy", new User(userId, ""));
            update.set("lastUpdatedOn", new Date());
            update.set("location", new Location(locationId));

            update.where(builder.equal(rootPerson.get("id"), personId));

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

            if (1 == total) {
                log.info("Person updated employe_id: " + personId);
                transaction.commit();

                success = true;
            } else {
                log.error("Person can not be updated " + personId);
                transaction.rollback();
            }
        } catch (HibernateException e) {
            log.error("Person cannot be updated " + personId, e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method updatePersonById(" + personId + ") ", e);
            rollback(transaction);
        }
        return success;
    }
    
    public boolean updatePersonCustomerById(String firstName, String secondName,
            String lastName, String middleName, Date birthdate,
            String personId, String userId, Float payment, float adeudo, String locationId) {
        log.info("updateEmployeeById");

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

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

            if (null != payment) {
                update.set("payment", payment);
            }
            update.set("firstName", firstName);
            update.set("secondName", secondName);
            update.set("lastName", lastName);
            update.set("middleName", middleName);
            update.set("birthdate", birthdate);
            update.set("lastUpdatedBy", new User(userId, ""));
            update.set("lastUpdatedOn", new Date());
            update.set("adeudo", adeudo);
            update.set("location", new Location(locationId));

            update.where(builder.equal(rootPerson.get("id"), personId));

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

            if (1 == total) {
                log.info("Person updated employe_id: " + personId);
                transaction.commit();

                success = true;
            } else {
                log.error("Person can not be updated " + personId);
                transaction.rollback();
            }
        } catch (HibernateException e) {
            log.error("Person cannot be updated " + personId, e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method updatePersonById(" + personId + ") ", e);
            rollback(transaction);
        }
        return success;
    }

    /**
     * Add RFC, Email, CURP, and Local/Mobile phones to person.
     *
     * @param person RFC, CURP, Email contact person details.
     * @param userName User to load and use to set createBy/updateBy user in the
     * record.
     * @param numbers MOBILE/HOME contact numbers fo person list.
     * @param save true save otherwise update.
     *
     * @return True if the details was saved/updated successfully otherwise
     * false.
     */
    public boolean addPersonContactDetails(Person person, String userName, List<ContactNumber> numbers, boolean save) {
        log.info("addPersonContactDetails");

        boolean success = false;

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

            /**
             * Taxi Servicios goes for user details.
             */
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<User> criteria = builder.createQuery(User.class);
            Root<User> root = criteria.from(User.class);
            Path<String> idPath = root.get("id");
            Path<String> userNamePath = root.get("userName");

            criteria.select(builder.construct(User.class, idPath, userNamePath));
            criteria.where(builder.equal(root.get("userName"), userName));

            User user = session.createQuery(criteria).uniqueResult();

            builder = session.getCriteriaBuilder();
            CriteriaUpdate<Person> update = builder.createCriteriaUpdate(Person.class);
            Root<Person> rootEmployee = update.from(Person.class);

            update.set("rfc", person.getRfc());
            update.set("curp", person.getCurp());
            update.set("mail", person.getMail());
            update.set("lastUpdatedBy", user);
            update.set("lastUpdatedOn", person.getLastUpdatedOn());

            update.where(builder.equal(rootEmployee.get("id"), person.getId()));

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

            if (1 == total) {
                log.info("Contact details updated");
            }

            if (save) {
                numbers.forEach((number) -> {
                    number.setCreatedBy(user);
                    number.setCreatedOn(new Date());
                });
                log.info("Number details saved");
            } else {
                numbers.forEach((number) -> {
                    number.setLastUpdatedBy(user);

                });
                log.info("Number details updated");
            }
            transaction.commit();

            success = true;
        } catch (HibernateException e) {
            log.error("Person contact details can not be saved ", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method addPersonContactDetails() ", e);
            rollback(transaction);
        }
        return success;
    }

    /**
     * Save or update RFC, Email, CURP, and Local/Mobile phones to person
     * detials.
     *
     * @param personId (Client/Employee/Provider/Driver).
     * @param curp Clave Única de Registro de Población.
     * @param rfc Registro Federal de Contribuyentes.
     * @param email Mail.
     * @param phones MOBILE/HOME contact numbers fo person list.
     * @param userName User to load and use to set createBy/updateBy user in the
     * record.
     * @param saveLocalNumber true save local number otherwise update.
     * @param saveMobile true save mobile number otherwise update.
     *
     * @return True if all person detials were saved/updated successfully
     * otherwise false.
     */
    public boolean saveOrUpdatePersonContactDetailsById(String personId,
            String curp, String rfc, String email, List<ContactNumber> phones,
            String userName, boolean saveLocalNumber, boolean saveMobile) {
        log.info("updateEmployeeContactDetailsById");

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

            /**
             * Taxi Servicios goes for user details.
             */
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<User> criteria = builder.createQuery(User.class);
            Root<User> root = criteria.from(User.class);
            Path<String> idPath = root.get("id");
            Path<String> userNamePath = root.get("userName");

            criteria.select(builder.construct(User.class, idPath, userNamePath));
            criteria.where(builder.equal(root.get("userName"), userName));

            User user = session.createQuery(criteria).uniqueResult();

            builder = session.getCriteriaBuilder();
            CriteriaUpdate<Person> update = builder.createCriteriaUpdate(Person.class);
            Root<Person> rootEmployee = update.from(Person.class);

            update.set("rfc", rfc);
            update.set("curp", curp);
            update.set("mail", email);
            update.set("lastUpdatedBy", user);
            update.set("lastUpdatedOn", new Date());

            update.where(builder.equal(rootEmployee.get("id"), personId));

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

            if (1 == total) {
                log.info("Contact details updated");
            }

            builder = session.getCriteriaBuilder();
            CriteriaQuery<Person> criteriaEmployee = builder.createQuery(Person.class);
            Root<Person> rootPerson = criteriaEmployee.from(Person.class);
            Path<String> idPathPerson = rootPerson.get("id");

            criteriaEmployee.select(builder.construct(Person.class, idPathPerson));
            criteriaEmployee.where(builder.equal(rootPerson.get("id"), personId));

            Person person = session.createQuery(criteriaEmployee).uniqueResult();

            for(ContactNumber phone: phones) {
                phone.setPerson(person);
                switch (phone.getPhoneType()) {
                    case HOME:
                        if (saveLocalNumber) {
                            phone.setCreatedBy(user);
                            phone.setCreatedOn(new Date());
                            session.save(phone);
                        } else {
                            updatePhone(phone, user, new Date());
                            
                        }
                        break;
                    case MOBILE:
                        if (saveMobile) {
                            phone.setCreatedBy(user);
                            phone.setCreatedOn(new Date());
                            session.save(phone);
                        } else {
                            updatePhone(phone, user, new Date());
                        }
                        break;
                }

            }

            transaction.commit();

            success = true;

            log.info("Person contact details updated " + personId);
        } catch (HibernateException e) {
            log.error("Person contact details cannot be updated " + personId, e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method saveOrUpdatePersonContactDetailsById(" + personId + ") ", e);
            rollback(transaction);
        }
        return success;
    }
    
    public boolean saveOrUpdateCustomerContactDetailsById(String personId,
            String curp, String rfc, String email, List<ContactNumber> phones,
            String userName, boolean saveLocalNumber, boolean saveMobile) {
        log.info("updateEmployeeContactDetailsById");

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

            /**
             * Taxi Servicios goes for user details.
             */
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<User> criteria = builder.createQuery(User.class);
            Root<User> root = criteria.from(User.class);
            Path<String> idPath = root.get("id");
            Path<String> userNamePath = root.get("userName");

            criteria.select(builder.construct(User.class, idPath, userNamePath));
            criteria.where(builder.equal(root.get("userName"), userName));

            User user = session.createQuery(criteria).uniqueResult();

            builder = session.getCriteriaBuilder();
            CriteriaUpdate<Person> update = builder.createCriteriaUpdate(Person.class);
            Root<Person> rootEmployee = update.from(Person.class);

            update.set("rfc", rfc);
            update.set("curp", curp);
            update.set("mail", email);
            update.set("lastUpdatedBy", user);
            update.set("lastUpdatedOn", new Date());

            update.where(builder.equal(rootEmployee.get("id"), personId));

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

            if (1 == total) {
                log.info("Contact details updated");
            }

            builder = session.getCriteriaBuilder();
            CriteriaQuery<Person> criteriaEmployee = builder.createQuery(Person.class);
            Root<Person> rootPerson = criteriaEmployee.from(Person.class);
            Path<String> idPathPerson = rootPerson.get("id");

            criteriaEmployee.select(builder.construct(Person.class, idPathPerson));
            criteriaEmployee.where(builder.equal(rootPerson.get("id"), personId));

            Person person = session.createQuery(criteriaEmployee).uniqueResult();

            for(ContactNumber phone: phones) {
                phone.setPerson(person);
                switch (phone.getPhoneType()) {
                    case HOME:
                        if (saveLocalNumber) {
                            phone.setCreatedBy(user);
                            phone.setCreatedOn(new Date());
                            session.save(phone);
                        } else {
                            updatePhone(phone, user, new Date());
                            
                        }
                        break;
                    case MOBILE:
                        if (saveMobile) {
                            phone.setCreatedBy(user);
                            phone.setCreatedOn(new Date());
                            session.save(phone);
                        } else {
                            updatePhone(phone, user, new Date());
                        }
                        break;
                }

            }

            transaction.commit();

            success = true;

            log.info("Person contact details updated " + personId);
        } catch (HibernateException e) {
            log.error("Person contact details cannot be updated " + personId, e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method saveOrUpdatePersonContactDetailsById(" + personId + ") ", e);
            rollback(transaction);
        }
        return success;
    }

    /**
     * Save or update new person address details.
     *
     * @param address Address person details.
     * @param save validate if save or update.
     * @param personId
     * @param userName User to load and use to set createBy/updateBy user in the
     * record.
     *
     * @return True if address was save or update successfully otherwise false.
     */
    public boolean saveOrUpdateAddress(Address address, boolean save,
            String personId, String userName) {
        log.info("saveOrUpdateAddress");

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

            /**
             * Taxi Servicios goes for user details.
             */
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<User> criteria = builder.createQuery(User.class);
            Root<User> root = criteria.from(User.class);
            Path<String> idPath = root.get("id");
            Path<String> userNamePath = root.get("userName");

            criteria.select(builder.construct(User.class, idPath, userNamePath));
            criteria.where(builder.equal(root.get("userName"), userName));

            User user = session.createQuery(criteria).uniqueResult();

            builder = session.getCriteriaBuilder();
            CriteriaQuery<Person> criteriaEmployee = builder.createQuery(Person.class);
            Root<Person> rootPerson = criteriaEmployee.from(Person.class);
            Path<String> idPathPerson = rootPerson.get("id");

            criteriaEmployee.select(builder.construct(Person.class, idPathPerson));
            criteriaEmployee.where(builder.equal(rootPerson.get("id"), personId));

            Person employee = session.createQuery(criteriaEmployee).uniqueResult();

            if (save) {
                address.setPreferenced(true);
                address.setCreatedBy(user);
                address.setCreatedOn(new Date());
            } else {
                address.setLastUpdatedBy(user);
                address.setLastUpdatedOn(new Date());
            }

            address.setPerson(employee);
            session.saveOrUpdate(address);
            transaction.commit();

            success = true;

            log.info("Address updated " + address);
        } catch (HibernateException e) {
            log.error("Address cannot be updated " + address, e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method saveOrUpdateAddress(" + address + ") ", e);
            rollback(transaction);
        }
        return success;
    }

    /**
     * Save or update documents, available documents types: a.- IFE/INE b.-
     * License c.- CardImage d.- Selfie.
     *
     * @param docs Document listo to save/update in DB.
     * @param save True save otherwise update document.
     *
     * @return True if list of documents were saved or updated successfully.
     */
    public boolean saveOrUpdatePhotos(List<Document> docs, boolean save) {
        log.info("saveOrUpdatePhotos");

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

            if (save) {
                docs.forEach((Document doc) -> {
                    doc.setCreatedOn(new Date());
                    session.save(doc);
                    log.info("Documente saved " + doc);
                });
            } else {
                CriteriaBuilder builder = session.getCriteriaBuilder();
                CriteriaUpdate<Document> update = builder.createCriteriaUpdate(Document.class);
                Root<Document> root = update.from(Document.class);

                docs.forEach((Document doc) -> {
                    update.set("path", doc.getPath());
                    update.set("documentType", doc.getDocumentType());
                    update.set("fileName", doc.getFileName());
                    update.set("content", doc.getContent());
                    update.set("lastUpdatedBy", doc.getLastUpdatedBy());
                    update.set("lastUpdatedOn", new Date());

                    update.where(builder.equal(root.get("id"), doc.getId()));
                    session.createQuery(update).executeUpdate();
                    log.info("Person document " + doc + " before commit and update");
                });
            }
            transaction.commit();

            success = true;

            log.info("Documents " + docs + " uploaded ");
        } catch (HibernateException e) {
            log.error("Document " + docs + " cannot be uploaded ", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method saveOrUpdatePhotos(" + docs + ") ", e);
            rollback(transaction);
        }
        return success;
    }

    /**
     *
     * @param personId
     * @return
     */
    public List<Document> getAllDocumentsByPersonId(String personId) {
        log.info("getAllDocumentsByPersonId");

        List<Document> documents = null;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Document> query = builder.createQuery(Document.class);
            Root<Document> root = query.from(Document.class);

            Path<String> id = root.get("id");
            Path<String> path = root.get("path");
            Path<DocumentType> documentType = root.get("documentType");
            Path<String> fileName = root.get("fileName");
            Path<byte[]> content = root.get("content");

            query.select(builder.construct(Document.class, id, path, documentType, fileName, content));
            query.where(builder.equal(root.get("person"), personId));

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

            transaction.commit();

            log.info("Documents by person id " + personId + " uploaded ");
        } catch (HibernateException e) {
            log.error("Document by person id" + personId + " cannot be uploaded ", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method getAllDocumentsByPersonId(" + personId + ") ", e);
            rollback(transaction);
        }
        return documents;
    }

    /**
     * Get all services that client can contract.
     *
     * @param active To available or disable services.
     *
     * @return List of available services.
     */
    public List<Service> getAllServices(boolean active) {
        log.info("Start getAllPersonByType");

        List<Service> services = null;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Service> criteria = builder.createQuery(Service.class);
            Root<Service> root = criteria.from(Service.class);

            Path<String> id = root.get("id");
            Path<String> name = root.get("name");
            Path<Float> charge = root.get("charge");

            criteria.select(builder.construct(Service.class, id, name, charge));
            criteria.where(builder.equal(root.get("active"), active));

            criteria.orderBy(
                    builder.asc(root.get("name"))
            );

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

            transaction.commit();
            log.info("Services loaded");
        } catch (HibernateException e) {
            log.error("Services cannot be loaded", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method getAllServices() ", e);
            rollback(transaction);
        }
        return services;
    }

    public boolean activeDriverById(String personId) {
        log.info("activeDriverById");

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

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

            update.set("active", true);
            update.set("lastUpdatedOn", new Date());
            update.where(builder.equal(rootUpdate.get("id"), personId));

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

            if (1 == total) {
                transaction.commit();
                success = true;
                log.info("Person " + personId + " active");
            } else {
                transaction.rollback();
                log.error("Error Person active total: " + total);
            }
        } catch (HibernateException e) {
            log.error("Person can not be active ", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method activeDriverById() ", e);
            rollback(transaction);
        }
        return success;
    }

    /**
     *
     * @param personId
     * @param blackListDescription
     * @return
     */
    public boolean addToBlackListDriver(String personId, String blackListDescription) {
        log.info("addToBlackListDriver");

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

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

            update.set("active", false);
            update.set("blackListDescription", blackListDescription);
            update.set("blackList", GenericEnumType.ENABLED);
            update.set("lastUpdatedOn", new Date());
            update.where(builder.equal(rootUpdate.get("id"), personId));

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

            if (1 == total) {
                transaction.commit();
                success = true;
                log.info("Driveer " + personId + " added to black list");
            } else {
                transaction.rollback();
                log.error("Error was not added to black list");
            }
        } catch (HibernateException e) {
            log.error("Driver was not added to black list", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method addToBlackListDriver() ", e);
            rollback(transaction);
        }
        return success;
    }

    public boolean returnToPoolBlackListDriver(String personId) {
        log.info("addToBlackListDriver");

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

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

            update.set("active", false);
            update.set("root", false);
            update.set("blackList", null);
            update.set("lastUpdatedOn", new Date());
            update.where(builder.equal(rootUpdate.get("id"), personId));

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

            if (1 == total) {
                transaction.commit();
                success = true;
                log.info("Driveer " + personId + " added to black list");
            } else {
                transaction.rollback();
                log.error("Error was not added to black list");
            }
        } catch (HibernateException e) {
            log.error("Driver was not added to black list", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method addToBlackListDriver() ", e);
            rollback(transaction);
        }
        return success;
    }
    /**
     *
     * @param driverId
     * @return
     */
    public boolean deteleToCollectByDriverId(String driverId) {
        log.info("deteleToCollectByDriverId");

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

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaDelete<ToCollect> delete = builder.createCriteriaDelete(ToCollect.class);

            Root<ToCollect> root = delete.from(ToCollect.class);

            delete.where(builder.equal(root.get("driver"), new Person(driverId)));

            int total = session.createQuery(delete).executeUpdate();
            System.out.println("total: " + total);
            transaction.commit();

            success = true;
            log.info("All to collect by driver were deleted");
        } catch (HibernateException e) {
            log.error("To Collects can not be deleted", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method deteleToCollectByDriverId() ", e);
            rollback(transaction);
        }
        return success;
    }

    /**
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public List<Holiday> findHolidaysByRangeOfDates(Date startDate, Date endDate) {
        log.info("findHolidaysByRangeOfDates");

        List<Holiday> holidays = new ArrayList<>();
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Holiday> query = builder.createQuery(Holiday.class);

            Root<Holiday> root = query.from(Holiday.class);

            Path<String> id = root.get("id");
            Path<Date> holiday = root.get("holiday");

            Predicate initialDate = builder.greaterThanOrEqualTo(root.get("holiday"), startDate);
            Predicate lastDate = builder.lessThanOrEqualTo(root.get("holiday"), endDate);

            query.select(builder.construct(Holiday.class, id, holiday));
            query.where(builder.and(initialDate, lastDate));

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

            transaction.commit();
            log.info("findHolidaysByRangeOfDates total: " + holidays.size());
        } catch (HibernateException e) {
            log.error("Can not find the holidays", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method findHolidaysByRangeOfDates() ", e);
            rollback(transaction);
        }

        return holidays;
    }

    /**
     *
     * @param collects
     * @return
     */
    public boolean saveToCollect(List<ToCollect> collects) {
        log.info("saveToCollect");

        boolean success = false;
        Transaction transaction = null;

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

            collects.forEach(toCollect -> {
                session.save(toCollect);
            });

            transaction.commit();
            log.info("Save all to collect");

            success = true;
        } catch (HibernateException e) {
            log.error("Can not find the holidays", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method saveToCollect() ", e);
            rollback(transaction);
        }

        return success;
    }
    
        public Address getAddressByIdPerson(Person person) {

        Transaction transaction = null;
        Address result = null;

        try {
            log.info("Searching adress by id customer..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

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

            Path<String> idPath = root.get("id");
            Path<String> streetPath = root.get("street");
            Path<String> extendedAddressPath = root.get("extendedAddress");
            Path<String> localityPath = root.get("locality");
            Path<String> regionPath = root.get("region");
            Path<String> zipCodePath = root.get("zipCode");
         

            criteria.select(
                    builder.construct(Address.class, idPath, streetPath,extendedAddressPath,
                            localityPath, regionPath,
                            zipCodePath
                    ));

            criteria.where(builder.equal(root.get("person"), person));

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

            transaction.commit();
            log.info("Address founds");
        } catch (HibernateException e) {
            rollback(transaction);
            log.error("Can not load taxi object ", e);
        } catch (Exception e) {
            rollback(transaction);
            log.error("Method getTaxiById of Taxi", e);
        }

        return result;
    }
        
        public Address getAddressCustomerByIdPerson(Person person) {

        Transaction transaction = null;
        Address result = null;

        try {
            log.info("Searching adress by id customer..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

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

            Path<String> idPath = root.get("id");
            Path<String> streetPath = root.get("street");
            Path<String> extendedAddressPath = root.get("extendedAddress");
            Path<String> localityPath = root.get("locality");
            Path<String> regionPath = root.get("region");
            Path<String> zipCodePath = root.get("zipCode");
         

            criteria.select(
                    builder.construct(Address.class, idPath, streetPath,extendedAddressPath,
                            localityPath, regionPath,
                            zipCodePath
                    ));

            Predicate criterio = (builder.equal(root.get("person"), person));
            
            Predicate criterio2 = builder.equal(root.get("preferenced"),1);
            criteria.where(builder.and(criterio, criterio2));
            
           

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

            transaction.commit();
            log.info("Address founds");
        } catch (HibernateException e) {
            rollback(transaction);
            log.error("Can not load taxi object ", e);
        } catch (Exception e) {
            rollback(transaction);
            log.error("Method getTaxiById of Taxi", e);
        }

        return result;
    }
        
    public ContactNumber getContacNumberByIdPersonPhoneType(Person person,PhoneType type) {

        Transaction transaction = null;
        ContactNumber result = null;

        try {
            log.info("Searching contact number by id person..");
            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);

            Path<String> idPath = root.get("id");
            Path<String> phonePath = root.get("phone");
            Path<String> phoneTypePath = root.get("phoneType");
            Path<String> personPath = root.get("person");
            
         

            criteria.select(
                    builder.construct(ContactNumber.class, idPath, phonePath, phoneTypePath));
            
            
            criteria.where(
                    builder.and(
                            builder.equal(root.get("person"), person),
                            builder.equal(root.get("phoneType"), type)
                            
                    )
            );
            result = session.createQuery(criteria).uniqueResult();

            transaction.commit();
            log.info("Address founds");
        } catch (HibernateException e) {
            rollback(transaction);
            log.error("Can not load taxi object ", e);
        } catch (Exception e) {
            rollback(transaction);
            log.error("Method getTaxiById of Taxi", e);
        }

        return result;
    }
    
    public ContactNumber getContacNumberCustomerByIdPersonPhoneType(Person person,PhoneType type) {

        Transaction transaction = null;
        ContactNumber result = null;

        try {
            log.info("Searching contact number by id person..");
            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);

            Path<String> idPath = root.get("id");
            Path<String> phonePath = root.get("phone");
            Path<String> phoneTypePath = root.get("phoneType");
            Path<String> personPath = root.get("person");
            
         

            criteria.select(
                    builder.construct(ContactNumber.class, idPath, phonePath, phoneTypePath));
            
            
            criteria.where(
                    builder.and(
                            builder.equal(root.get("person"), person),
                            builder.equal(root.get("phoneType"), type),
                            builder.equal(root.get("preferenced"),1)
                            
                    )
            );
            result = session.createQuery(criteria).uniqueResult();

            transaction.commit();
            log.info("Address founds");
        } catch (HibernateException e) {
            rollback(transaction);
            log.error("Can not load taxi object ", e);
        } catch (Exception e) {
            rollback(transaction);
            log.error("Method getTaxiById of Taxi", e);
        }

        return result;
    }
    public boolean updateAddress(Address address, User userUpdate, Date updatedOn) {
        log.info("update address");

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

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

            update.set("street", address.getStreet());
            update.set("extendedAddress", address.getExtendedAddress());
            update.set("locality", address.getLocality());
            update.set("region", address.getRegion());
            update.set("zipCode", address.getZipCode());
            update.set("lastUpdatedBy", userUpdate);
            update.set("lastUpdatedOn", updatedOn);
            update.where(builder.equal(rootUpdate.get("id"),address.getId()));

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

            if (1 == total) {
                transaction.commit();
                success = true;
                log.info("Address" + address.getId() + " updated");
            } else {
                transaction.rollback();
                log.error("Error Address updated total: " + total);
            }
        } catch (HibernateException e) {
            log.error("Address can not be updated ", e);
            rollback(transaction);
        } catch (Exception e) {
            log.error("Method autorizar() ", e);
            rollback(transaction);
        }
        return success;
    }
    
    
    public boolean updatePhone(ContactNumber phone, User userUpdate, Date updatedOn) {
        log.info("update phone");

        boolean success = false;
      
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            

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

            update.set("phone", phone.getPhone());
            update.set("phoneType", phone.getPhoneType());    
            update.set("lastUpdatedBy", userUpdate);
            update.set("lastUpdatedOn", updatedOn);
            update.where(builder.equal(rootUpdate.get("id"),phone.getId()));

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

            if (1 == total) {
              
                success = true;
                log.info("Phone" + phone.getId() + " updated");
            } else {
                
                log.error("Error Phone updated total: " + total);
            }
        } catch (HibernateException e) {
            log.error("Phone can not be updated ", e);

        } catch (Exception e) {
            log.error("Method autorizar() ", e);
        
        }
        return success;
    }
    
    private static final long serialVersionUID = -4328523313989211889L;

    private final Logger log = LogManager.getLogger(GenericPersonController.class);

}
