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

import com.arrebol.taxiservicios.controller.util.HibernateUtil;
import com.arrebol.taxiservicios.model.admin.Expense;
import com.arrebol.taxiservicios.model.admin.FinancingCustomer;
import com.arrebol.taxiservicios.model.admin.PersonHasService;
import com.arrebol.taxiservicios.model.admin.PersonHasServiceId;
import com.arrebol.taxiservicios.model.admin.Service;
import com.arrebol.taxiservicios.model.admin.Taxi;
import com.arrebol.taxiservicios.model.catalog.Color;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.catalog.RegimenFiscal;
import com.arrebol.taxiservicios.model.catalog.Vehicle;
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.enums.BasicType;
import com.arrebol.taxiservicios.model.stocktaking.ServiceOrderHasProduct;
import com.arrebol.taxiservicios.model.stocktaking.ServiceOrderHasProductId;
import com.arrebol.taxiservicios.model.stocktaking.view.KardexInStocktakingView;
import com.arrebol.taxiservicios.model.stocktaking.view.KardexOutStocktakingView;
import com.crov.prase.model.prase.Incidence;
import java.io.Serializable;
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.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 class CustomerController extends GenericPersonController implements Serializable {

    public boolean addTaxi(Taxi taxi, String userId, String vehicleId, String colorId) {
        logger.info("addTaxi");

        boolean success = false;
        Transaction transaction = null;

        try {
            taxi.setColor(new Color(colorId));
            taxi.setVehicle(new Vehicle(vehicleId));

            User user = new User(userId, "");
            Person driver = null;
            taxi.setDriver(driver);

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

            taxi.setCreatedBy(user);

            session.save(taxi);
            transaction.commit();

            logger.info("Taxi saved " + taxi.getId());

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

    public boolean addVehiculo(Taxi taxi, User user) {
        logger.info("addVehiculo");
        boolean success = false;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            taxi.setId(UUID.randomUUID().toString());
            taxi.setCreatedBy(user);
            taxi.setCreatedOn(new Date());
            session.save(taxi);
            transaction.commit();

            logger.info("Vehiculo (Taxi) saved " + taxi.getId());
            success = true;
        } catch (HibernateException e) {
            logger.error("Vehiculo (Taxi) can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addVehiculo() ", e);
            rollback(transaction);
        }
        return success;
    }

    public boolean updateVehiculo(Taxi taxi, User user) {
        logger.info("addVehiculo");
        boolean success = false;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            
            taxi.setLastUpdatedBy(user);
            taxi.setLastUpdatedOn(new Date());
            session.update(taxi);
            transaction.commit();

            logger.info("Vehiculo (Taxi) saved " + taxi.getId());
            success = true;
        } catch (HibernateException e) {
            logger.error("Vehiculo (Taxi) can not be added ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addVehiculo() ", e);
            rollback(transaction);
        }
        return success;
    }

    public List<Taxi> fillTaxisComboBox() {

        Transaction transaction = null;
        List<Taxi> result = null;

        try {
            logger.info("Searching all taxis to select..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

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

            Path<String> idPath = root.get("id");
            Path<String> economicNumberPath = root.get("economicNumber");

            criteria.select(
                    builder.construct(Taxi.class, idPath, economicNumberPath
                    ));

            criteria.where(builder.equal(root.get("active"), Boolean.TRUE));

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

            result = session.createQuery(criteria).getResultList();
            transaction.commit();
            logger.info("Total of taxis found for ComboBox: " + (null == result ? -1 : result.size()));
        } catch (HibernateException e) {
            logger.error("Can not load list of taxis for ComboBox ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillTaxisComboBox of Expense", e);
            rollback(transaction);
        }

        return result;
    }

    public void editServicesHasProduct(ServiceOrderHasProductId id) {
        Transaction transaction = null;

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

            CriteriaUpdate<ServiceOrderHasProduct> update = builder.createCriteriaUpdate(ServiceOrderHasProduct.class);
            Root<ServiceOrderHasProduct> root = update.from(ServiceOrderHasProduct.class);

            update.set("cobrado", BasicType.ENEBLED);
            update.set("payCreatedBy", id.getPayCreatedBy());
            update.set("payDate", id.getPayDate());
            update.set("expense", id.getExpense());

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

            session.createQuery(update).executeUpdate();

            logger.info("The ServiceOrderHasProduct was edited");

            transaction.commit();
        } catch (HibernateException e) {
            logger.error("The ServiceOrderHasProduct can not be saved", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method editServicesHasProduct", e);
            rollback(transaction);
        }
    }

    public List<KardexOutStocktakingView> fillProductsDetailByOrderServicesFinancing(String taxiID) {
        logger.info("Searching all payment client..");

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

            String query = "SELECT exp FROM KardexOutStocktakingView exp "
                    + "WHERE exp.taxiId = :taxiId AND exp.estatus = 'FINISHED' AND exp.cobrado = 'No cobrado' AND exp.financiado = 'Financiado' "
                    + "ORDER BY exp.fecha DESC";

            result = session.createQuery(query)
                    .setParameter("taxiId", taxiID)
                    .getResultList();

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

        return result;
    }

    public List<KardexOutStocktakingView> fillProductsDetailByOrderServicesFinancingInvoice(String taxiID) {
        logger.info("Searching all products in service order");

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

            String query = "SELECT exp FROM KardexOutStocktakingView exp "
                    + "WHERE exp.taxiId = :taxiId AND exp.estatus = 'FINISHED' AND exp.cobrado = 'Cobrado'"
                    + "ORDER BY exp.fecha DESC";

            result = session.createQuery(query)
                    .setParameter("taxiId", taxiID)
                    .getResultList();

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

        return result;
    }

    public List<KardexInStocktakingView> fillProductsDetailByInvoice(String taxiID) {
        logger.info("Searching all products in invoice");

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

            String query = "SELECT exp FROM KardexInStocktakingView exp "
                    + "WHERE exp.taxiId = :taxiId "
                    + "ORDER BY exp.fecha DESC";

            result = session.createQuery(query)
                    .setParameter("taxiId", taxiID)
                    .getResultList();

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

        return result;
    }

    public List<Taxi> fillTaxisComboBoxFinance() {

        Transaction transaction = null;
        List<Taxi> result = null;

        try {
            logger.info("Searching all taxis to select..");
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder builder = session.getCriteriaBuilder();

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

            Path<String> id = root.get("id");
            Path<String> placa = root.get("placa");
            Path<String> year = root.get("year");
            Path<Vehicle> vehicle = root.get("vehicle");
            Path<Color> color = root.get("color");

            criteria.select(
                    builder.construct(Taxi.class, id,
                            placa, year, vehicle, color
                    ));

            criteria.orderBy(
                    builder.asc(root.get("placa"))
            );
            criteria.orderBy(
                    builder.asc(root.get("year"))
            );

            result = session.createQuery(criteria).getResultList();
            transaction.commit();
            logger.info("Total of taxis found for ComboBox: " + (null == result ? -1 : result.size()));
        } catch (HibernateException e) {
            logger.error("Can not load list of taxis for ComboBox ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillTaxisComboBox of Sale", e);
            rollback(transaction);
        }

        return result;
    }

    public List<Expense> fillExpenseDatatableLeftJoinToFinance(String taxiID) {
        logger.info("Searching all expenses..");

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

            String query = "SELECT exp FROM Expense exp "
                    + "JOIN Taxi tax ON exp.taxi = tax.id "
                    + "LEFT JOIN Person per ON exp.driver = per.id "
                    + "WHERE exp.type NOT IN ('INICIO', 'PAGO_CLIENTE','ABONO_FINANCIAMIENTO') AND exp.taxi = :taxi AND (exp.paid = 'DISABLED' AND exp.finance = 'ENEBLED') "
                    + "ORDER BY exp.createdOn DESC";

            result = session.createQuery(query)
                    .setParameter("taxi", new Taxi(taxiID))
                    .getResultList();

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

        return result;
    }

    public List<Expense> fillExpenseDatatableLeftJoinToFinanceInvoice(String taxiID) {
        logger.info("Searching all expenses..");

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

            String query = "SELECT exp FROM Expense exp "
                    + "JOIN Taxi tax ON exp.taxi = tax.id "
                    + "LEFT JOIN Person per ON exp.driver = per.id "
                    + "WHERE exp.type NOT IN ('INICIO', 'PAGO_CLIENTE','ABONO_FINANCIAMIENTO') AND exp.taxi = :taxi AND exp.paid = 'ENEBLED' "
                    + "ORDER BY exp.createdOn DESC";

            result = session.createQuery(query)
                    .setParameter("taxi", new Taxi(taxiID))
                    .getResultList();

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

        return result;
    }

    public Double getTotalAdeudosByLocation(Location location) {
        logger.info("Searching all expenses..");

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

            String query = "SELECT SUM(plf.adeudo) "
                    + "FROM Taxi  plf "
                    + "WHERE plf.location = :location";

            result = (double) session.createQuery(query)
                    .setParameter("location", location).uniqueResult();

            transaction.commit();
            logger.info("Total: " + result);
        } catch (HibernateException e) {
            logger.error("Can not load list of expenses for ComboBox ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method fillExpenseDatatable of Expense", e);
            rollback(transaction);
        }

        return result;
    }

    public void editExpenseToPay(Expense expense) {
        Transaction transaction = null;

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

            CriteriaUpdate<Expense> update = builder.createCriteriaUpdate(Expense.class);
            Root<Expense> root = update.from(Expense.class);

            update.set("paid", BasicType.ENEBLED);
            update.set("paymentDate", expense.getPaymentDate());

            update.where(builder.equal(root.get("id"), expense.getId()));

            session.createQuery(update).executeUpdate();

            logger.info("The Expense was edited");

            transaction.commit();
        } catch (HibernateException e) {
            logger.error("The ServiceOrderHasProduct can not be saved", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method editServicesHasProduct", e);
            rollback(transaction);
        }
    }

    public Taxi getTaxiById(String taxiId) {

        Transaction transaction = null;
        Taxi result = null;

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

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

            Path<String> idPath = root.get("id");
            Path<String> economicNumberPath = root.get("economicNumber");
            Path<String> vehiclePath = root.get("vehicle");
            Path<String> colorPath = root.get("color");
            Path<String> placaPath = root.get("placa");
            Path<String> serialNumberPath = root.get("serialNumber");
            Path<String> motorNmumberPath = root.get("motorNmumber");
            Path<String> commentsPath = root.get("comments");
            Path<String> yearPath = root.get("year");
            Path<String> insuranceNumber = root.get("insuranceNumber");
            Path<Date> insuranceEndDate = root.get("insuranceEndDate");
            Path<Float> adeudo = root.get("adeudo");

            criteria.select(
                    builder.construct(Taxi.class, idPath, economicNumberPath,
                            vehiclePath, colorPath,
                            placaPath, serialNumberPath, motorNmumberPath,
                            commentsPath, yearPath, insuranceNumber, insuranceEndDate, adeudo
                    ));

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

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

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

        return result;
    }

    /**
     * Get all services that client has already contrated.
     *
     * @param customerId Customer number.
     *
     * @return List of available services.
     */
    public List<PersonHasService> getAllServicesByCustomer(String customerId) {
        logger.info("Start getAllServicesByCustomer");

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

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

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

            criteria.select(builder.construct(PersonHasService.class, id));
            criteria.where(builder.equal(root.get("person"), new Person(customerId)));

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

            transaction.commit();
            logger.info("Services loaded");
        } catch (HibernateException e) {
            logger.error("Services cannot be loaded", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method getAllServicesByCustomer() ", e);
            rollback(transaction);
        }
        return personHasServices;
    }

    /**
     * Save or update the services tahta a customer has contrated.
     *
     * @param customerId Customer number.
     * @param servicesIn Services that customer wants to contract.
     * @param servicesOut Services taht customer wants to quit.
     *
     * @return True if success savinf/updating services contracted otherwise
     * false.
     */
    public boolean saveOrUpdatePersonHasServices(String customerId,
            List<Service> servicesIn, List<Service> servicesOut) {
        logger.info("Start saveOrUpdatePersonHasServices");

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

            servicesOut.forEach((out) -> {
                session.delete(
                        new PersonHasService(
                                new PersonHasServiceId(
                                        customerId, out.getId()
                                )
                        )
                );
                logger.info("Services by customer were deleted");
            });

            servicesIn.forEach((in) -> {
                session.saveOrUpdate(
                        new PersonHasService(
                                new PersonHasServiceId(
                                        customerId, in.getId()
                                )
                        )
                );
                logger.info("Services by customer were saved");
            });

            transaction.commit();
            success = true;
            logger.info("Services by Customer saved");
        } catch (HibernateException e) {
            logger.error("Services by customer can not be saved", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method saveOrUpdatePersonHasServices() ", e);
            rollback(transaction);
        }
        return success;
    }

    public boolean saveOrUpdatePersonCommercialInvoice(PersonCommercialInvoice personCommercialInvoice, String idUser, String regimenFiscal) {
        logger.info("Start saveOrUpdatePersonHasServices");

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

            if (personCommercialInvoice.getId() != null) {
                CriteriaUpdate<PersonCommercialInvoice> update = builder.createCriteriaUpdate(PersonCommercialInvoice.class);
                Root<PersonCommercialInvoice> root = update.from(PersonCommercialInvoice.class);

                update.set("businessName", personCommercialInvoice.getBusinessName());
                update.set("address", personCommercialInvoice.getAddress());
                update.set("country", personCommercialInvoice.getCountry());
                update.set("municipality", personCommercialInvoice.getMunicipality());
                update.set("rfc", personCommercialInvoice.getRfc());
                update.set("postalCode", personCommercialInvoice.getPostalCode());
                update.set("suburb", personCommercialInvoice.getSuburb());
                update.set("state", personCommercialInvoice.getState());
                update.set("regimenFiscal", new RegimenFiscal(regimenFiscal));

                update.where(builder.equal(root.get("id"), personCommercialInvoice.getId()));

                session.createQuery(update).executeUpdate();

                logger.info("The commercialInvoice data were updated");

            } else {

                personCommercialInvoice.setId(UUID.randomUUID().toString());
                if (regimenFiscal != null && !regimenFiscal.isEmpty()) {
                    personCommercialInvoice.setRegimenFiscal(new RegimenFiscal(regimenFiscal));
                }

                session.save(personCommercialInvoice);
                logger.info("The commercialInvoice data were saved");
            }

            transaction.commit();
            success = true;
            logger.info("Services by Customer saved");
        } catch (HibernateException e) {
            logger.error("Services by customer can not be saved", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method saveOrUpdatePersonHasServices() ", e);
            rollback(transaction);
        }
        return success;
    }

    public List<Taxi> getTaxiByIdCustomer(String taxiId, String idLocation) {

        Transaction transaction = null;
        List<Taxi> result = null;

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

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

            Path<String> id = root.get("id");
            Path<String> placa = root.get("placa");
            Path<String> year = root.get("year");
            Path<Vehicle> vehicle = root.get("vehicle");
            Path<Color> color = root.get("color");
            Path<Float> adeudo = root.get("adeudo");

            criteria.select(
                    builder.construct(Taxi.class, id,
                            placa, year, vehicle, color, adeudo
                    ));

            criteria.where(builder.and(builder.equal(root.get("customer"), new Person(taxiId)), builder.equal(root.get("location"), new Location(idLocation))));

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

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

        return result;
    }

    public List<FinancingCustomer> getFinancingByIdTaxi(String taxiId) {

        Transaction transaction = null;
        List<FinancingCustomer> result = null;

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

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

            Path<String> id = root.get("id");
            Path<Double> lastDebit = root.get("lastDebit");
            Path<Double> monthDebit = root.get("monthDebit");
            Path<Double> increase = root.get("increase");
            Path<Double> discount = root.get("discount");
            Path<String> commentsDiscount = root.get("commentsDiscount");
            Path<String> commentsIncrease = root.get("commentsIncrease");
            Path<Double> payment = root.get("payment");
            Path<Double> actuallyDebit = root.get("actuallyDebit");
            Path<Date> createdOn = root.get("createdOn");

            criteria.select(
                    builder.construct(FinancingCustomer.class, id,
                            lastDebit, monthDebit, increase, discount, commentsDiscount, commentsIncrease, payment, actuallyDebit, createdOn
                    ));

            criteria.where(builder.equal(root.get("taxi"), new Taxi(taxiId)));

            criteria.orderBy(
                    builder.desc(root.get("createdOn"))
            );

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

            transaction.commit();
            logger.info("Financing founds");
        } catch (HibernateException e) {
            rollback(transaction);
            logger.error("Can not load Financing object ", e);
        } catch (Exception e) {
            rollback(transaction);
            logger.error("Method getFinancingByIdTaxi of financing", e);
        }

        return result;
    }

    public boolean updateContactNumber(ContactNumber number, User user) {
        logger.info("updateContactNumber");
        boolean success = false;
        Transaction transaction = null;

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

            number.setLastUpdatedOn(new Date());
            number.setLastUpdatedBy(user);
            session.update(number);
            transaction.commit();
            logger.info("ContactNumber updated " + number.getId());

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

    public List<ContactNumber> fillPreferencedContactNumberByPerson(String idPerson) {
        logger.info("fillContactNumberByPerson");
        List<ContactNumber> resultList = null;
        Transaction transaction = null;
        try {
            logger.info("Searching ContactNumber for 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);

            Predicate criterio1 = builder.equal(root.get("person").get("id"), idPerson);
            criteria.where(builder.and(criterio1));
            criteria.orderBy(builder.desc(root.get("createdOn")));

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

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

    private static final long serialVersionUID = -4554850459591575426L;

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

}
