package com.rjconsultores.ventaboletos.dao.hibernate;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;

import javax.sql.DataSource;

import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.rjconsultores.ventaboletos.constantes.Constantes;
import com.rjconsultores.ventaboletos.dao.ConferenciaComissaoDAO;
import com.rjconsultores.ventaboletos.dao.ContaCorrenteAgenciaDAO;
import com.rjconsultores.ventaboletos.entidad.Conferencia;
import com.rjconsultores.ventaboletos.entidad.ContaCorrentePtoVta;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.LogConferencia;
import com.rjconsultores.ventaboletos.entidad.PuntoVenta;
import com.rjconsultores.ventaboletos.enums.comissao.StatusLogConferencia;
import com.rjconsultores.ventaboletos.exception.BusinessException;
import com.rjconsultores.ventaboletos.utilerias.ApplicationProperties;
import com.rjconsultores.ventaboletos.utilerias.CustomEnum;
import com.rjconsultores.ventaboletos.utilerias.DateUtil;
import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado;
import com.rjconsultores.ventaboletos.vo.comissao.BoletoComissao;
import com.rjconsultores.ventaboletos.vo.comissao.ConferenciaComissaoVO;
import com.rjconsultores.ventaboletos.vo.comissao.DiaConferenciaComissaoVO;
import com.rjconsultores.ventaboletos.vo.comissao.EventosFinanceirosVO;
import com.rjconsultores.ventaboletos.vo.comissao.FormaPagoEventosFinanceirosVO;
import com.rjconsultores.ventaboletos.vo.comissao.FormapagoVO;
import com.rjconsultores.ventaboletos.vo.comissao.LogConferenciaVO;
import com.rjconsultores.ventaboletos.vo.comissao.OcdVO;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;

@Repository("conferenciaComissaoDAO")
public class ConferenciaComissaoHibernateDAO extends GenericHibernateDAO<Conferencia, Long>
		implements ConferenciaComissaoDAO {

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

	@Autowired
	private ContaCorrenteAgenciaDAO contaCorrenteAgenciaDAO;

	@Autowired
	private DataSource dataSourceRead;

	@Autowired
	private DataSource dataSource;

	@Autowired
	public ConferenciaComissaoHibernateDAO(@Qualifier("sessionFactory") SessionFactory factory) {
		setSessionFactory(factory);
	}

	@Override
	public List<ConferenciaComissaoVO> carregarConferenciaComissao(String competencia,
			Empresa empresa, PuntoVenta puntoVenta, Date dataMovimento, boolean isDesconsideraPtVendaFechados) throws BusinessException {
		Connection con = null;
		try {
			con = getConnection();

			List<ConferenciaComissaoVO> lsConferencias = new ArrayList<ConferenciaComissaoVO>();

			carregarPuntoVentas(lsConferencias, competencia, empresa, puntoVenta, dataMovimento, isDesconsideraPtVendaFechados);
			carregarConferenciasRegistradas(lsConferencias, competencia, empresa, puntoVenta, dataMovimento, null, null, null);
			carregarMovimentoVendas(con, lsConferencias, competencia, empresa, puntoVenta, dataMovimento, null, null);
			carregarDiasSemMovimento(lsConferencias, competencia, empresa, puntoVenta, dataMovimento);

			Collections.sort(lsConferencias);

			return lsConferencias;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		} finally {
			try {
				if (con != null && !con.isClosed()) {
					con.close();
				}
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
	}

	public List<ConferenciaComissaoVO> carregarConferenciaComissao(Date dataInicial, Date dataFinal,
			Empresa empresa, PuntoVenta puntoVenta, Date dataMovimento, boolean isDesconsideraPtVendaFechados) throws BusinessException {
		Connection con = null;
		try {
			con = getConnection();

			List<ConferenciaComissaoVO> lsConferencias = new ArrayList<ConferenciaComissaoVO>();
			Map<String, Object> parametros = carregarParametros(dataInicial, dataFinal, null, empresa, puntoVenta, dataMovimento, false);

			SimpleDateFormat format = new SimpleDateFormat("MM/yyyy");
			String competencia = format.format(dataInicial);

			carregarPuntoVentas(lsConferencias, dataInicial, dataFinal, empresa, puntoVenta, dataMovimento);
			carregarConferenciasRegistradas(lsConferencias, null, empresa, puntoVenta, dataMovimento, null, null, parametros);
			carregarMovimentoVendas(con, lsConferencias, null, empresa, puntoVenta, dataMovimento, dataInicial, dataFinal);
			carregarDiasSemMovimento(lsConferencias, competencia, empresa, puntoVenta, dataMovimento);

			return lsConferencias;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		} finally {
			try {
				if (con != null && !con.isClosed()) {
					con.close();
				}
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
	}

	private void carregarPuntoVentas(List<ConferenciaComissaoVO> lsConferencias, Date dataInicial, Date dataFinal,
			Empresa empresa, PuntoVenta puntoVenta, Date dataMovimento) throws BusinessException {

		Set<Integer> diasSemMovimentos = DateUtil.carregarDiasCompetencia(dataInicial, dataFinal);
		ConferenciaComissaoVO conferenciaComissao = new ConferenciaComissaoVO();
		conferenciaComissao.setPuntoventaId(puntoVenta.getPuntoventaId());
		conferenciaComissao.setNombpuntoventa(puntoVenta.getNombpuntoventa());
		conferenciaComissao.setNumPuntoVenta(puntoVenta.getNumPuntoVenta());
		conferenciaComissao.setDataInicial(dataInicial);
		conferenciaComissao.setDataFinal(dataFinal);
		conferenciaComissao.setDiasSemMovimentos(diasSemMovimentos);
		lsConferencias.add(conferenciaComissao);

		return;
	}

	@SuppressWarnings("unchecked")
	private void carregarPuntoVentas(List<ConferenciaComissaoVO> lsConferencias, String competencia,
			Empresa empresa, PuntoVenta puntoVenta, Date dataMovimento, boolean isDesconsideraPtVendaFechados) throws BusinessException {
		try {
			if (puntoVenta != null && puntoVenta.getPuntoventaId() > -1) {
				Set<Integer> diasSemMovimentos = DateUtil.carregarDiasCompetencia(competencia, dataMovimento);
				ConferenciaComissaoVO conferenciaComissao = new ConferenciaComissaoVO();
				conferenciaComissao.setPuntoventaId(puntoVenta.getPuntoventaId());
				conferenciaComissao.setNombpuntoventa(puntoVenta.getNombpuntoventa());
				conferenciaComissao.setNumPuntoVenta(puntoVenta.getNumPuntoVenta());
				conferenciaComissao.setCompetencia(competencia);
				conferenciaComissao.setDiasSemMovimentos(diasSemMovimentos);
				lsConferencias.add(conferenciaComissao);

				return;
			}

			Map<String, Object> parametros = new HashMap<String, Object>();
			StringBuilder sQuery = new StringBuilder()
					.append("SELECT PV.PUNTOVENTA_ID AS \"puntoventaId\", ")
					.append("PV.NUMPUNTOVENTA as \"numPuntoVenta\", PV.NOMBPUNTOVENTA as \"nombpuntoventa\" ")
					.append("FROM PUNTO_VENTA PV ")
					.append("JOIN PTOVTA_EMPRESA PTE ON PTE.PUNTOVENTA_ID = PV.PUNTOVENTA_ID AND PTE.ACTIVO = 1 ")
					.append("WHERE PV.ACTIVO = 1 ");

			if (empresa != null) {
				sQuery.append("AND PTE.EMPRESA_ID = :empresaId ");
				parametros.put("empresaId", empresa.getEmpresaId());
			}
			
			if(isDesconsideraPtVendaFechados) {
				sQuery.append("AND PV.STATUSAPROBACION = 'A' ");
			}

			sQuery.append("ORDER BY PV.NOMBPUNTOVENTA ");

			@SuppressWarnings("deprecation")
			Query qr = getSession().createSQLQuery(sQuery.toString())
					.addScalar("puntoventaId", Hibernate.INTEGER)
					.addScalar("numPuntoVenta", Hibernate.STRING)
					.addScalar("nombpuntoventa", Hibernate.STRING)
					.setResultTransformer(Transformers.aliasToBean(ConferenciaComissaoVO.class));
			setParametros(qr, parametros);

			processarQueryConferenciaComissao(qr.list(), lsConferencias, competencia, dataMovimento, null, null);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	@SuppressWarnings("unchecked")
	private void carregarConferenciasRegistradas(List<ConferenciaComissaoVO> lsConferencias,
			String competencia, Empresa empresa, PuntoVenta puntoVenta, Date dataMovimento, Date dataInicial, Date dataFinal, Map<String, Object> parametros) throws BusinessException {
		try {
			if (parametros == null) {
				parametros = carregarParametros(dataInicial, dataFinal, competencia, empresa, puntoVenta, dataMovimento, false);
			}
			StringBuilder sQuery = new StringBuilder("SELECT co FROM Conferencia co ");
			sQuery.append("JOIN co.empresa em ")
					.append("JOIN co.puntoVenta pv ")
					.append("WHERE co.activo = 1 ")
					.append("AND co.datamovimento BETWEEN TO_DATE(:dataInicial,'DD/MM/YYYY HH24:MI') AND TO_DATE(:dataFinal,'DD/MM/YYYY HH24:MI') ");

			if (parametros.containsKey("empresaId")) {
				sQuery.append("AND em.empresaId = :empresaId ");
			}
			if (parametros.containsKey("puntoventaId")) {
				sQuery.append("AND pv.puntoventaId = :puntoventaId ");
			}
			
			Query qr = getSession().createQuery(sQuery.toString());
			setParametros(qr, parametros);
			dataInicial = parametros.get("dataInicial") != null ? DateUtil.getDateFromString(parametros.get("dataInicial").toString(), "dd/MM/yyyy HH:mm") : null;
			dataFinal = parametros.get("dataFinal") != null ? DateUtil.getDateFromString(parametros.get("dataFinal").toString(), "dd/MM/yyyy HH:mm") : null;
			processarQueryConferencia(qr.list(), lsConferencias, competencia, dataMovimento, dataInicial, dataFinal);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	@SuppressWarnings("rawtypes")
	private void setParametros(Query qr, Map<String, Object> parametros) {
		for (Entry<String, Object> parametro : parametros.entrySet()) {
			if (parametro.getValue() instanceof Collection) {
				qr.setParameterList(parametro.getKey(), (Collection) parametro.getValue());
			} else if (parametro.getValue() instanceof List) {
				qr.setParameterList(parametro.getKey(), (List) parametro.getValue());
			} else {
				qr.setParameter(parametro.getKey(), parametro.getValue());
			}
		}
	}
	
	private void setParametros(NamedParameterStatement npst, Map<String, Object> parametros) throws SQLException {
		for (Entry<String, Object> parametro : parametros.entrySet()) {
			npst.setObject(parametro.getKey(), parametro.getValue());
		}
	}

	private void carregarMovimentoVendas(Connection con, List<ConferenciaComissaoVO> lsConferencias,
			String competencia, Empresa empresa, PuntoVenta puntoVenta, Date dataMovimento, Date dataInicialDate, Date dataFinalDate)
			throws BusinessException, SQLException {
		PreparedStatement stmt = null;
		ResultSet rset = null;
		try {

			Map<String, Object> parametros = carregarParametros(dataInicialDate, dataFinalDate, competencia, empresa, puntoVenta, dataMovimento, false);

			StringBuilder sQuery = new StringBuilder()
					.append("SELECT PV.PUNTOVENTA_ID AS \"puntoventaId\", PV.NUMPUNTOVENTA as \"numPuntoVenta\", ")
					.append("PV.NOMBPUNTOVENTA as \"nombpuntoventa\", TO_DATE(C.FECCORTE, 'DD/MM/YY') as \"datamovimento\" ")
					.append("FROM CAJA C ")
					.append("INNER JOIN PUNTO_VENTA PV ON C.PUNTOVENTA_ID = PV.PUNTOVENTA_ID ")
					.append("INNER JOIN MARCA M ON C.MARCA_ID = M.MARCA_ID ")
					.append("WHERE PV.ACTIVO = 1 ")
					.append("AND ((C.INDSTATUSBOLETO = 'E' AND C.INDREIMPRESION = 1) OR C.INDREIMPRESION = 0 OR C.MOTIVOCANCELACION_ID = ?) ")
					.append("AND C.FECCORTE BETWEEN TO_DATE(?, 'DD/MM/YYYY HH24:MI') AND TO_DATE(?, 'DD/MM/YYYY HH24:MI') ");

			if (parametros.containsKey("empresaId")) {
				sQuery.append("AND M.EMPRESA_ID = ? ");
			}
			if (parametros.containsKey("puntoventaId")) {
				sQuery.append("AND PV.PUNTOVENTA_ID = ? ");
			}
			
			sQuery.append(" UNION ")
				  .append(" SELECT PV.PUNTOVENTA_ID AS \"puntoventaId\", PV.NUMPUNTOVENTA as \"numPuntoVenta\", ")
				  .append(" PV.NOMBPUNTOVENTA as \"nombpuntoventa\", TO_DATE(C.FECCORTE, 'DD/MM/YY') as \"datamovimento\" ")
				  .append(" FROM EVENTO_EXTRA ee ")
				  .append(" INNER JOIN CAJA_DIVERSOS C ON C.EVENTOEXTRA_ID = EE.EVENTOEXTRA_ID ")
				  .append(" INNER JOIN punto_venta  pv ON ee.puntoventa_id = pv.puntoventa_id ")
				  .append(" WHERE ee.activo = 1")
				  .append(" AND C.FECCORTE BETWEEN TO_DATE(?, 'DD/MM/YYYY HH24:MI') AND TO_DATE(?, 'DD/MM/YYYY HH24:MI') ");
		 
			if (parametros.containsKey("empresaId")) {
				sQuery.append("AND ee.EMPRESA_ID = ? ");
			}
			
			if (parametros.containsKey("puntoventaId")) {
				sQuery.append("AND PV.PUNTOVENTA_ID = ? ");
			}  

			sQuery.append("GROUP BY PV.PUNTOVENTA_ID, PV.NUMPUNTOVENTA, PV.NOMBPUNTOVENTA, TO_DATE(C.FECCORTE, 'DD/MM/YY') ");

			int idxParametro = 1;
			stmt = con.prepareStatement(sQuery.toString());
			String dataIncial = (String) parametros.get("dataInicial");
			String dataFinal = (String) parametros.get("dataFinal");
			stmt.setInt(idxParametro++, Constantes.MVO_CANCEL_GERACAO_OCD.intValue());
			stmt.setString(idxParametro++, dataIncial);
			stmt.setString(idxParametro++, dataFinal);
			if (parametros.containsKey("empresaId")) {
				stmt.setInt(idxParametro++, (Integer) parametros.get("empresaId"));
			}
			if (parametros.containsKey("puntoventaId") && ((Integer)parametros.get("puntoventaId")) != -1) {
				stmt.setInt(idxParametro++, (Integer) parametros.get("puntoventaId"));
			}
			
			//Parametros Evento extra
			stmt.setString(idxParametro++, dataIncial);
			stmt.setString(idxParametro++, dataFinal);
			
			if (parametros.containsKey("empresaId")) {
				stmt.setInt(idxParametro++, (Integer) parametros.get("empresaId"));
			}
			
			if (parametros.containsKey("puntoventaId") && ((Integer)parametros.get("puntoventaId")) != -1) {
				stmt.setInt(idxParametro++, (Integer) parametros.get("puntoventaId"));
			}

			rset = stmt.executeQuery();
			List<ConferenciaComissaoVO> movimentos = new ArrayList<ConferenciaComissaoVO>();
			while (rset.next()) {
				ConferenciaComissaoVO conferenciaComissao = new ConferenciaComissaoVO();
				conferenciaComissao.setPuntoventaId(rset.getInt("puntoventaId"));
				conferenciaComissao.setNumPuntoVenta(rset.getString("numPuntoVenta"));
				conferenciaComissao.setNombpuntoventa(rset.getString("nombpuntoventa"));
				conferenciaComissao.setDataMovimento(rset.getDate("datamovimento"));

				movimentos.add(conferenciaComissao);
			}

			processarQueryConferenciaComissao(movimentos, lsConferencias, competencia, dataMovimento, dataInicialDate, dataFinalDate);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		} finally {
			if (rset != null && !rset.isClosed()) {
				rset.close();
			}
			if (stmt != null && !stmt.isClosed()) {
				stmt.close();
			}
		}
	}

	/**
	 * Carrega a {@link ConferenciaComissaoVO} a partir de uma consulta com sql nativo, transformando o resultado em uma coleção de {@link ConferenciaComissaoVO}
	 * 
	 * @param lsQuery
	 * @param lsConferencias
	 * @param competencia
	 * @param corPadrao
	 * @throws ParseException
	 */
	private void processarQueryConferenciaComissao(List<ConferenciaComissaoVO> lsQuery,
			List<ConferenciaComissaoVO> lsConferencias, String competencia, Date dataMovimento, Date dataInicial, Date dataFinal) throws ParseException {

		Set<Integer> diasSemMovimentos = new TreeSet<Integer>();
		if(dataInicial != null && dataFinal != null) {
			diasSemMovimentos = DateUtil.carregarDiasCompetencia(dataInicial, dataFinal);
		}
		
		if (competencia != null) {
			diasSemMovimentos = DateUtil.carregarDiasCompetencia(competencia, dataMovimento);
		}

		for (ConferenciaComissaoVO conferenciaComissaoMovimentoDiario : lsQuery) {
			ConferenciaComissaoVO conferenciaComissao = new ConferenciaComissaoVO();
			conferenciaComissao.setCompetencia(competencia);
			conferenciaComissao.setDataInicial(dataInicial);
			conferenciaComissao.setDataFinal(dataFinal);
			conferenciaComissao.setPuntoventaId(conferenciaComissaoMovimentoDiario.getPuntoventaId());
			conferenciaComissao.setNumPuntoVenta(conferenciaComissaoMovimentoDiario.getNumPuntoVenta());
			conferenciaComissao.setNombpuntoventa(conferenciaComissaoMovimentoDiario.getNombpuntoventa());
			conferenciaComissao.setDiasSemMovimentos(new TreeSet<Integer>(diasSemMovimentos));

			if (lsConferencias.contains(conferenciaComissao)) {
				conferenciaComissao = lsConferencias.get(lsConferencias.indexOf(conferenciaComissao));
			}

			if (conferenciaComissaoMovimentoDiario.getDataMovimento() != null) {
				Integer dia = Integer.valueOf(DateUtil.getStringDate(conferenciaComissaoMovimentoDiario.getDataMovimento(), "dd"));
				if (conferenciaComissao.getDiasSemMovimentos() != null && conferenciaComissao.getDiasSemMovimentos().contains(dia)) {

					DiaConferenciaComissaoVO diaConferenciaComissao = new DiaConferenciaComissaoVO();
					diaConferenciaComissao.setDia(dia);
					if (competencia != null) {
						diaConferenciaComissao.setData(DateUtil.getDateFromString(dia + "/" + competencia, "dd/MM/yyyy"));
					} else {
						diaConferenciaComissao.setData(dataMovimento);
					}

					if (conferenciaComissao.getDias() == null) {
						conferenciaComissao.setDias(new ArrayList<DiaConferenciaComissaoVO>());
					}

					conferenciaComissao.getDias().add(diaConferenciaComissao);
					conferenciaComissao.getDiasSemMovimentos().remove(diaConferenciaComissao.getDia());
				}
			}

			if (!lsConferencias.contains(conferenciaComissao)) {
				lsConferencias.add(conferenciaComissao);
			}
		}
	}

	/**
	 * Carrega a {@link ConferenciaComissaoVO} a partir dos registros da tabela {@link Conferencia}
	 * 
	 * @param lsQuery
	 * @param lsConferencias
	 * @param competencia
	 * @throws ParseException
	 */
	private void processarQueryConferencia(List<Conferencia> lsQuery,
			List<ConferenciaComissaoVO> lsConferencias, String competencia, Date dataMovimento, Date dataInicial, Date dataFinal) throws ParseException {
		if (lsQuery != null && !lsQuery.isEmpty()) {
			Set<Integer> diasSemMovimentos = null;
			if (competencia != null) {
				diasSemMovimentos = DateUtil.carregarDiasCompetencia(competencia, dataMovimento);
			}
			for (Conferencia conferencia : lsQuery) {
				ConferenciaComissaoVO conferenciaComissao = new ConferenciaComissaoVO();
				conferenciaComissao.setCompetencia(competencia);
				conferenciaComissao.setDataInicial(dataInicial);
				conferenciaComissao.setDataFinal(dataFinal);
				conferenciaComissao.setPuntoventaId(conferencia.getPuntoVenta().getPuntoventaId());
				conferenciaComissao.setNumPuntoVenta(conferencia.getPuntoVenta().getNumPuntoVenta());
				conferenciaComissao.setNombpuntoventa(conferencia.getPuntoVenta().getNombpuntoventa());
				conferenciaComissao.setDiasSemMovimentos(diasSemMovimentos == null ? null : new TreeSet<Integer>(diasSemMovimentos));

				if (lsConferencias.contains(conferenciaComissao)) {
					conferenciaComissao = lsConferencias.get(lsConferencias.indexOf(conferenciaComissao));
				}

				if (conferencia.getDatamovimento() != null) {
					Integer dia = Integer.valueOf(DateUtil.getStringDate(conferencia.getDatamovimento(), "dd"));
					if (conferenciaComissao.getDiasSemMovimentos() != null && conferenciaComissao.getDiasSemMovimentos().contains(dia)) {

						DiaConferenciaComissaoVO diaConferenciaComissao = new DiaConferenciaComissaoVO();
						diaConferenciaComissao.setConferenciaId(conferencia.getConferenciaId());
						diaConferenciaComissao.setDia(dia);
						if (competencia != null) {
							diaConferenciaComissao.setData(DateUtil.getDateFromString(dia + "/" + competencia, "dd/MM/yyyy"));
						} else {
							diaConferenciaComissao.setData(dataMovimento);
						}
						diaConferenciaComissao.setIndboletogerado(conferencia.getIndboletogerado());
						diaConferenciaComissao.setIndconferido(conferencia.getIndconferido());
						diaConferenciaComissao.setIndmaloterecebido(conferencia.getIndmaloterecebido());
						diaConferenciaComissao.setIndpendencia(conferencia.getIndpendencia());
						diaConferenciaComissao.setIndsemmovimento(conferencia.getIndsemmovimento());

						if (conferenciaComissao.getDias() == null) {
							conferenciaComissao.setDias(new ArrayList<DiaConferenciaComissaoVO>());
						}

						conferenciaComissao.getDias().add(diaConferenciaComissao);
						conferenciaComissao.getDiasSemMovimentos().remove(diaConferenciaComissao.getDia());
					}
				}

				if (!lsConferencias.contains(conferenciaComissao)) {
					lsConferencias.add(conferenciaComissao);
				}
			}
		}
	}

	private void carregarDiasSemMovimento(List<ConferenciaComissaoVO> lsConferencias,
			String competencia, Empresa empresa, PuntoVenta puntoVenta, Date dataMovimento) throws ParseException {
		for (ConferenciaComissaoVO conferenciaComissao : lsConferencias) {
			for (Integer diaSemMovimento : conferenciaComissao.getDiasSemMovimentos()) {
				DiaConferenciaComissaoVO diaConferenciaComissao = new DiaConferenciaComissaoVO();
				diaConferenciaComissao.setDia(diaSemMovimento);
				if (competencia == null && diaSemMovimento != null) {
					diaConferenciaComissao.setData(dataMovimento);
				} else {
					diaConferenciaComissao.setData(DateUtil.getDateFromString(diaSemMovimento + "/" + competencia, "dd/MM/yyyy"));
				}
				diaConferenciaComissao.setIndsemmovimento(true);

				if (conferenciaComissao.getDias() == null) {
					conferenciaComissao.setDias(new ArrayList<DiaConferenciaComissaoVO>());
				}
				conferenciaComissao.getDias().add(diaConferenciaComissao);
			}
			conferenciaComissao.getDiasSemMovimentos().clear();
		}
	}

	private Map<String, Object> carregarParametros(Date dataInicial, Date dataFinal, String competencia, Empresa empresa,
			PuntoVenta puntoVenta, Date datamovimento, boolean formatoDataSemHora) throws ParseException {
		Map<String, Object> parametros = new HashMap<String, Object>();

		String formatoData = (formatoDataSemHora ? "dd/MM/yyyy" : "dd/MM/yyyy HH:mm");

		if (empresa != null) {
			parametros.put("empresaId", empresa.getEmpresaId());
		}
		if (puntoVenta != null && puntoVenta.getPuntoventaId() > -1) {
			parametros.put("puntoventaId", puntoVenta.getPuntoventaId());
		}

		if (datamovimento != null) {
			parametros.put("dataInicial", DateUtil.getStringDate(DateUtil.inicioFecha(datamovimento), formatoData));
			parametros.put("dataFinal", DateUtil.getStringDate(DateUtil.fimFecha(datamovimento), formatoData));
		}

		if (StringUtils.isNotBlank(competencia) && datamovimento == null) {
			parametros.put("dataInicial", DateUtil.getStringDate(DateUtil.inicioFecha(DateUtil.getDataInicialCompetencia(competencia)), formatoData));
			parametros.put("dataFinal", DateUtil.getStringDate(DateUtil.fimFecha(DateUtil.getDataFinalCompetencia(competencia)), formatoData));
		}

		if (parametros.get("dataInicial") == null && dataInicial != null) {
			parametros.put("dataInicial", DateUtil.getStringDate(dataInicial, formatoData));
			parametros.put("dataFinal", DateUtil.getStringDate(dataFinal, formatoData));
		}

		return parametros;
	}

	@Override
	@Transactional
	public Conferencia confirmarChegadaMalote(Conferencia conferencia) throws BusinessException {
		try {
			conferencia.setIndmaloterecebido(Boolean.TRUE);
			if (conferencia.isSemPendenciaConferencia()) {
				return encerrarMovimentoDiario(conferencia);
			}
			return suscribirOrActualizacion(conferencia);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	@Override
	@Transactional
	public Conferencia cancelarChegadaMalote(Conferencia conferencia) {
		conferencia.setIndmaloterecebido(Boolean.FALSE);
		return suscribirOrActualizacion(conferencia);
	}

	@Override
	@Transactional
	public Conferencia suscribirOrActualizacion(Conferencia entidad) {
		if (entidad.getConferenciaId() == null) {
			return suscribir(entidad);
		} else {
			return actualizacion(entidad);
		}
	}

	@Override
	@Transactional
	public Conferencia encerrarMovimentoDiario(Conferencia conferencia) throws BusinessException {
		try {
			conferencia.setIndconferido(Boolean.TRUE);
			conferencia.setIndpendencia(isMovimentoDiarioPendencia(conferencia));
			conferencia.setIndboletogerado(isMovimentoDiarioBoletoGerado(conferencia));

			gerarLancamentoContaCorrente(conferencia);
			return suscribirOrActualizacion(conferencia);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	@Override
	@Transactional
	public Conferencia reabrirMovimentoDiario(Conferencia conferencia) throws BusinessException {
		try {
			conferencia.setIndconferido(Boolean.FALSE);
			return suscribirOrActualizacion(conferencia);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	private boolean isMovimentoDiarioBoletoGerado(Conferencia conferencia)
			throws BusinessException {
		try {
			Map<String, Object> parametros = carregarParametros(null, null, null, conferencia.getEmpresa(), conferencia.getPuntoVenta(), null, false);
			StringBuilder sQuery = new StringBuilder()
					.append("SELECT FECHAMENTOCNTCORRENTE_ID ")
					.append("FROM FECHAMENTO_CNTCORRENTE ")
					.append("WHERE ACTIVO = 1 ")
					.append("AND :datamovimento BETWEEN FECINIFECHAMENTO AND FECFINFECHAMENTO ");

			parametros.put("datamovimento", conferencia.getDatamovimento());
			if (parametros.containsKey("empresaId")) {
				sQuery.append("AND EMPRESA_ID = :empresaId ");
			}
			if (parametros.containsKey("puntoventaId")) {
				sQuery.append("AND PUNTOVENTA_ID = :puntoventaId ");
			}

			Query qr = getSession().createSQLQuery(sQuery.toString());
			setParametros(qr, parametros);

			return !qr.list().isEmpty();
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	private boolean isMovimentoDiarioPendencia(Conferencia conferencia) {
		Query qr = getSession().createQuery(
				"SELECT COUNT(log) FROM LogConferencia log WHERE log.activo = 1 AND log.conferencia.conferenciaId = :conferenciaId AND log.status = :status");
		qr.setParameter("conferenciaId", conferencia.getConferenciaId());
		qr.setParameter("status", StatusLogConferencia.PENDENCIA);
		return !qr.list().isEmpty() && ((Long) qr.list().get(0)) > 0;
	}

	@Override
	public List<EventosFinanceirosVO> carregarEventosFinanceiros(Conferencia conferencia)
			throws BusinessException {
		Connection con = null;
		NamedParameterStatement npst = null;
		ResultSet rSet = null;
		
		try {
			Map<String, Object> parametros = carregarParametros(conferencia.getDataInicial(), conferencia.getDataFinal(), conferencia.getCompetencia(), conferencia.getEmpresa(),
					conferencia.getPuntoVenta(), conferencia.getDatamovimento(), true);
			StringBuilder sQuery = new StringBuilder()
					.append("SELECT DISTINCT EE.BOLETO_ID AS \"boletoId\", EE.EVENTOEXTRA_ID AS \"eventoextraId\", EE.NUMDOCUMENTO AS \"numdocumento\", ")
					.append("CFP.IMPORTE AS \"impingreso\", TEE.DESCTIPOEVENTO AS \"desctipoevento\", EE.DESCINFO AS \"descinfo\", ")
					.append("NVL(LOG.STATUS,-1) AS \"status\", FP.FORMAPAGO_ID AS \"formapagoId\", FP.DESCPAGO AS \"descpago\", ")
					.append("TEE.INDTIPO AS \"indtipo\", U.NOMBUSUARIO AS \"nombusuario\", LOG.CONFERENCIA_ID AS \"logconferenciaId\",  ")
					.append("COMFP.COMEMPFORMAPAGO_ID AS \"comempformapagoId\", COMTEE.COMEMPTIPOEVENTOEXTRA_ID AS \"comemptipoeventoextraId\", ")
					.append("COALESCE(CEC.INDTIPO_DEB_CRED, 0)  AS \"tipoeventoextradebcred\", ")
					.append("CEC.INDEVENTOSFINANCEIROS AS \"exigeConferenciaAba\", B.NUMFOLIOSISTEMA \"numFolioSistema\", ")
					.append("TEE.CVETIPOEVENTO AS \"cvetipoevento\", CD.FECCORTE AS \"feccorte\", ")
					.append("EI.ICMS as \"icmsBase\", NVL(EST.ESTADO_ID,0) as \"estadoId\", CD.CAJADIVERSOS_ID as cajaDiversosId, U.USUARIO_ID as usuarioId, ")
					.append("CD.TURNO_ID as turnoId ")
					.append("FROM EVENTO_EXTRA EE ")
					.append("JOIN TIPO_EVENTO_EXTRA TEE ON EE.TIPOEVENTOEXTRA_ID = TEE.TIPOEVENTOEXTRA_ID ")
					.append("JOIN CAJA_DIVERSOS CD ON CD.EVENTOEXTRA_ID = EE.EVENTOEXTRA_ID ")
					.append("JOIN CAJA_DIVERSOS_PAGO CFP ON CFP.CAJADIVERSOS_ID = CD.CAJADIVERSOS_ID ")
					.append("JOIN FORMA_PAGO FP ON FP.FORMAPAGO_ID = CFP.FORMAPAGO_ID ")
					.append("INNER JOIN USUARIO U ON EE.USUARIO_ID = U.USUARIO_ID ")
					.append("LEFT JOIN COM_EMP_CONFERENCIA CEC ON EE.EMPRESA_ID = CEC.EMPRESA_ID AND CEC.ACTIVO = 1 ")
					.append("LEFT JOIN LOG_CONFERENCIA LOG ON LOG.EVENTOEXTRA_ID = EE.EVENTOEXTRA_ID AND LOG.ACTIVO = 1 ")
					.append("LEFT JOIN COM_EMP_FORMAPAGO COMFP ON COMFP.FORMAPAGO_ID = FP.FORMAPAGO_ID AND COMFP.EMPRESA_ID = EE.EMPRESA_ID AND COMFP.ACTIVO = 1 ")
					.append("LEFT JOIN COM_EMP_TIPOEVENTOEXTRA COMTEE ON COMTEE.TIPOEVENTOEXTRA_ID = TEE.TIPOEVENTOEXTRA_ID AND COMTEE.EMPRESA_ID = EE.EMPRESA_ID AND COMTEE.ACTIVO = 1 ")
					.append("LEFT JOIN BOLETO B ON B.BOLETO_ID = EE.BOLETO_ID ")
					.append("LEFT JOIN PARADA ORI ON ORI.PARADA_ID = B.ORIGEN_ID ")
					.append("LEFT JOIN CIUDAD CID ON CID.CIUDAD_ID = ORI.CIUDAD_ID ")
					.append("LEFT JOIN ESTADO EST ON EST.ESTADO_ID = CID.ESTADO_ID ")
					.append("LEFT JOIN MARCA M ON B.MARCA_ID = M.MARCA_ID ")
					.append("LEFT JOIN EMPRESA E ON E.EMPRESA_ID = M.EMPRESA_ID ")
					.append("LEFT JOIN EMPRESA_IMPOSTO EI ON (EI.ESTADO_ID = EST.ESTADO_ID AND EI.EMPRESA_ID = E.EMPRESA_ID AND EI.ACTIVO = 1) ")
					.append("WHERE EE.ACTIVO = 1 ")
					.append("AND CD.FECCORTE BETWEEN TO_DATE(:dataInicial, 'DD/MM/YYYY') AND TO_DATE(:dataFinal, 'DD/MM/YYYY') ");

			if (parametros.containsKey("empresaId")) {
				sQuery.append("AND EE.EMPRESA_ID = :empresaId ");
			}
			if (parametros.containsKey("puntoventaId")) {
				sQuery.append("AND CD.PUNTOVENTA_ID = :puntoventaId ");
			}
			sQuery.append("ORDER BY TEE.DESCTIPOEVENTO ");
			
			con = getConnection();
			npst = new NamedParameterStatement(con, sQuery.toString());
			setParametros(npst, parametros);
			rSet = npst.executeQuery();
			
			List<EventosFinanceirosVO> result = new ArrayList<EventosFinanceirosVO>();
			while(rSet.next()) {
				EventosFinanceirosVO eventosFinanceiros = new EventosFinanceirosVO(rSet.getLong("eventoextraId"), rSet.getLong("logconferenciaId") > 0 ? rSet.getLong("logconferenciaId") : 0);
				eventosFinanceiros.setBoletoId(rSet.getLong("boletoId") > 0 ? rSet.getLong("boletoId") : null);
				eventosFinanceiros.setNumdocumento(rSet.getString("numdocumento"));
				eventosFinanceiros.setImpingreso(rSet.getBigDecimal("impingreso"));
				eventosFinanceiros.setDesctipoevento(rSet.getString("desctipoevento"));
				eventosFinanceiros.setDescinfo(rSet.getString("descinfo"));
				eventosFinanceiros.setStatus(rSet.getInt("status") >= 0 ? rSet.getInt("status") : null);
				eventosFinanceiros.setFormapagoId(rSet.getInt("formapagoId") > 0 ? rSet.getInt("formapagoId") : null);
				eventosFinanceiros.setDescpago(rSet.getString("descpago"));
				eventosFinanceiros.setComempformapagoId(rSet.getInt("comempformapagoId") > 0 ? rSet.getInt("comempformapagoId") : null);
				eventosFinanceiros.setComemptipoeventoextraId(rSet.getInt("comemptipoeventoextraId") > 0 ? rSet.getInt("comemptipoeventoextraId") : null);
				eventosFinanceiros.setTipoeventoextradebcred(rSet.getInt("tipoeventoextradebcred") > 0 ? rSet.getInt("tipoeventoextradebcred") : null);
				eventosFinanceiros.setIndtipo(rSet.getString("indtipo"));
				eventosFinanceiros.setNombusuario(rSet.getString("nombusuario"));
				eventosFinanceiros.setExigeConferenciaAba(rSet.getBoolean("exigeConferenciaAba"));
				eventosFinanceiros.setNumFolioSistema(rSet.getString("numFolioSistema"));
				eventosFinanceiros.setCvetipoevento(rSet.getString("cvetipoevento"));
				eventosFinanceiros.setFeccorte(rSet.getDate("feccorte"));
				eventosFinanceiros.setIcmsBase(rSet.getBigDecimal("icmsBase"));
				eventosFinanceiros.setEstadoId(rSet.getInt("estadoId") > 0 ? rSet.getInt("estadoId") : null);
				eventosFinanceiros.setCajaDiversosId(rSet.getLong("cajaDiversosId"));
				eventosFinanceiros.setUsuarioId(rSet.getInt("usuarioId"));
				eventosFinanceiros.setTurnoId(rSet.getInt("turnoId"));
				
				eventosFinanceiros.setConferencia(conferencia);
								
				
				if (result.contains(eventosFinanceiros)) {
					int indice = result.indexOf(eventosFinanceiros);
					EventosFinanceirosVO aux = result.get(indice);
					FormaPagoEventosFinanceirosVO formapagoVO = new FormaPagoEventosFinanceirosVO(eventosFinanceiros.getFormapagoId(),eventosFinanceiros.getDescpago(),eventosFinanceiros.getImpingreso());
					aux.getFormapagos().add(formapagoVO);
					result.set(indice, aux);
				}else {
					eventosFinanceiros.setFormapagos(new ArrayList<FormaPagoEventosFinanceirosVO>());
					eventosFinanceiros.getFormapagos().add(new FormaPagoEventosFinanceirosVO(eventosFinanceiros.getFormapagoId(),eventosFinanceiros.getDescpago(),eventosFinanceiros.getImpingreso()));
				    result.add(eventosFinanceiros);
				}
				
			}

			return result;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		} finally {
			try {
				if(rSet != null && !rSet.isClosed()) {
					rSet.close();
				}
				if(npst != null && !npst.isClosed()) {
					npst.close();
				}
				if(con != null && !con.isClosed()) {
					con.close();
				}
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<LogConferenciaVO> carregarLogConferencia(Conferencia conferencia)
			throws BusinessException {
		try {
			if (conferencia != null && conferencia.getConferenciaId() != null) {
				StringBuilder sQuery = new StringBuilder()
						.append("SELECT LOG.LOGCONFERENCIA_ID AS \"logconferenciaId\", LOG.OBSERVACAO AS \"observacao\", LOG.PRECO AS \"preco\", ")
						.append("LOG.STATUS AS \"status\", NVL(B.NUMFOLIOSISTEMA,C.NUMFOLIOSISTEMA) AS \"numfoliosistema\", LOG.TIPO AS \"tipo\", ")
						.append("O.NUMOPERACION AS \"numoperacion\", TEE.DESCTIPOEVENTO AS \"desctipoevento\", U.NOMBUSUARIO AS \"nombusuario\", ")
						.append("LOG.FECMODIF AS \"fecmodif\", LOG.INDCREDITO AS \"indcredito\", B.BOLETO_ID AS \"boletoId\", O.OCD_ID AS \"ocdId\", ")
						.append("EE.EVENTOEXTRA_ID AS \"eventoextraId\", TI.DESCTIPO AS \"desctipoinformativo\", LOG.CONFERENCIAPENDENCIA_ID as \"pendenciaId\", ")
						.append("CP.DESCPENDENCIA AS \"descpendencia\", LOG.INDMESMODIA AS \"descComportamentoData\", C.CAJA_ID AS \"cajaId\" ")
						.append("FROM LOG_CONFERENCIA LOG ")
						.append("LEFT JOIN BOLETO B ON B.BOLETO_ID = LOG.BOLETO_ID ")
						.append("LEFT JOIN CAJA C ON C.CAJA_ID = LOG.CAJA_ID ")
						.append("LEFT JOIN EVENTO_EXTRA EE ON EE.EVENTOEXTRA_ID = LOG.EVENTOEXTRA_ID ")
						.append("LEFT JOIN TIPO_EVENTO_EXTRA TEE ON TEE.TIPOEVENTOEXTRA_ID = EE.TIPOEVENTOEXTRA_ID ")
						.append("LEFT JOIN OCD O ON O.OCD_ID = LOG.OCD_ID ")
						.append("LEFT JOIN TIPO_INFORMATIVO TI ON TI.TIPOINFORMATIVO_ID = LOG.TIPOINFORMATIVOCOMISSAO_ID ")
						.append("LEFT JOIN CONFERENCIA_PENDENCIA CP ON CP.CONFERENCIAPENDENCIA_ID = LOG.CONFERENCIAPENDENCIA_ID ")
						.append("JOIN USUARIO U ON U.USUARIO_ID = LOG.USUARIO_ID ")
						.append("WHERE LOG.ACTIVO = 1 ")
						.append("AND LOG.CONFERENCIA_ID = :conferenciaId  ORDER BY LOGCONFERENCIA_ID");

				@SuppressWarnings("deprecation")
				Query qr = getSession().createSQLQuery(sQuery.toString())
						.addScalar("logconferenciaId", Hibernate.LONG)
						.addScalar("observacao", Hibernate.STRING)
						.addScalar("preco", Hibernate.BIG_DECIMAL)
						.addScalar("descComportamentoData", Hibernate.STRING)
						.addScalar("status", Hibernate.INTEGER)
						.addScalar("numfoliosistema", Hibernate.STRING)
						.addScalar("tipo", Hibernate.INTEGER)
						.addScalar("numoperacion", Hibernate.STRING)
						.addScalar("desctipoevento", Hibernate.STRING)
						.addScalar("nombusuario", Hibernate.STRING)
						.addScalar("fecmodif", Hibernate.TIMESTAMP)
						.addScalar("indcredito", Hibernate.SHORT)
						.addScalar("boletoId", Hibernate.LONG)
						.addScalar("ocdId", Hibernate.LONG)
						.addScalar("eventoextraId", Hibernate.LONG)
						.addScalar("desctipoinformativo", Hibernate.STRING)
						.addScalar("descpendencia", Hibernate.STRING)
						.addScalar("cajaId", Hibernate.LONG)
						.addScalar("pendenciaId", Hibernate.INTEGER)
						.setResultTransformer(Transformers.aliasToBean(LogConferenciaVO.class));
				qr.setParameter("conferenciaId", conferencia.getConferenciaId());

				List<LogConferenciaVO> result = qr.list();

				for (LogConferenciaVO l : result) {
					l.setConferencia(conferencia);
				}

				return result;
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}

		return new ArrayList<LogConferenciaVO>();
	}

	@Override
	@Transactional
	public LogConferencia suscribirLogConferencia(LogConferencia logConferencia)
			throws BusinessException {
		try {
			logConferencia.setActivo(Boolean.TRUE);
			logConferencia.setUsuario(UsuarioLogado.getUsuarioLogado());
			logConferencia.setFecmodif(new Date());
			
			if (logConferencia.getConferencia().getConferenciaId() == null) {
				logConferencia.setConferencia(suscribir(logConferencia.getConferencia()));
			}

			getSession().save(logConferencia);
			return logConferencia;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	@Override
	@Transactional
	public void borrarLogConferencia(LogConferencia logConferencia) throws BusinessException {
		try {
			if(logConferencia == null) {
				return;
			}
			
			if (logConferencia.getContaCorrentePtoVta() != null) {
				ContaCorrentePtoVta contaCorrentePtoVta = logConferencia.getContaCorrentePtoVta();
				contaCorrentePtoVta.setActivo(Boolean.FALSE);
				contaCorrentePtoVta.setFecmodif(logConferencia.getFecmodif());
				contaCorrentePtoVta.setUsuario(logConferencia.getUsuario());

				contaCorrenteAgenciaDAO.actualizacion(contaCorrentePtoVta);
			}
			
			logConferencia.setActivo(Boolean.FALSE);
			logConferencia.setUsuario(UsuarioLogado.getUsuarioLogado());
			logConferencia.setFecmodif(new Date());
			
			getSession().merge(logConferencia);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	@Override
	public LogConferencia obtenerLogConferenciaID(Long logconferenciaId) {
		try {
			return (LogConferencia) this.getHibernateTemplate().get(LogConferencia.class.getName(), logconferenciaId);
		} catch (final HibernateException ex) {
			throw convertHibernateAccessException(ex);
		}
	}

	@Override
	public List<BoletoComissao> carregarBilhetesComissao(Conferencia conferencia, boolean isCalculoComissao, boolean isConsideraBilhetesDevolvidosEmOutraAgencia)
			throws BusinessException {
		
		Connection con = null;
		NamedParameterStatement npst = null;
		ResultSet rSet = null;
		
		try {
			Map<String, Object> parametros = carregarParametros(conferencia.getDataInicial(), conferencia.getDataFinal(), conferencia.getCompetencia(), conferencia.getEmpresa(),
					conferencia.getPuntoVenta(), conferencia.getDatamovimento(), true);

			StringBuilder sQuery = new StringBuilder()
					.append("SELECT DISTINCT C.CAJA_ID AS \"cajaId\", C.NUMASIENTO AS \"numAsiento\", C.NUMASIENTOVINCULADO AS \"numAsientoVinculado\", C.NUMOPERACION AS \"numoperacion\", C.NUMFOLIOSISTEMA AS \"numFolioSistema\", ")
					.append("C.NUMSERIEPREIMPRESA AS \"numSeriePreimpresa\", C.NUMFOLIOPREIMPRESO AS \"numFolioPreImpreso\", EST.CVEESTADO AS \"uf\", CAT.DESCCATEGORIA AS \"desccategoria\", ")
					.append("NVL(C.PRECIOBASE,0) AS \"valorbase\", NVL(C.PRECIOPAGADO,0) AS \"valorpagado\", NVL(C.IMPORTEOUTROS,0) AS \"seguroOutros\", NVL(C.IMPORTEPEDAGIO,0) AS \"pedagio\", NVL(C.IMPORTESEGURO,0) AS \"seguro\", ")
					.append("NVL(C.IMPORTETAXAEMBARQUE,0) AS \"embarque\", C.TIPOVENTA_ID AS \"tipoVenta\", C.INDSTATUSBOLETO AS \"indstatusboleto\", NVL(LOG.STATUS,-1) AS \"status\", FP.FORMAPAGO_ID AS \"formapagoId\", ")
					.append("FP.DESCPAGO AS \"descpago\", LOG.LOGCONFERENCIA_ID AS \"logconferenciaId\", MC.DESCMOTIVO AS \"descmotivocancelacion\", U.NOMBUSUARIO AS \"nombusuario\", C.MOTIVOCANCELACION_ID AS \"motivocancelacionId\", ")
					.append("CF.IMPORTE AS \"importeFp\", COMFP.COMEMPFORMAPAGO_ID AS \"comempformapagoId\", ")
					.append("(select max(COMEMPCATEGORIA_ID) from COM_EMP_CATEGORIA where CATEGORIA_ID = C.CATEGORIA_ID AND EMPRESA_ID  = M.EMPRESA_ID AND ACTIVO = 1) AS \"comempcategoriaId\", C.NOMBPASAJERO AS \"nombpasajero\", ")
					.append("E.INDCARBOLETOSDEVOLVIDOSCONF AS \"indcarboletosdevolvidosconf\", C.FECCORRIDA AS \"feccorrida\", C.CORRIDA_ID \"corridaId\", ")
					.append("case when t.tarifa_id is not null then nvl(t.precio, 0) + nvl(t.importepedagio, 0) + nvl(t.importetaxaembarque, 0) + nvl(t.importeseguro, 0) + nvl ")
				    .append("(t.importeoutros, 0) else nvl(c.preciobase,0) + nvl(c.importepedagio, 0) + nvl(c.importetaxaembarque, 0) + nvl(c.importeseguro, 0) + nvl ")
				    .append("(c.importeoutros, 0) end AS \"valorTabela\"," )
					.append("C.INDCANCELACION AS \"indCancelacion\", C.INDREIMPRESION AS \"indreimpresion\", C.FECCORTE AS \"feccorte\", C.TRANSACAOORIGINAL_ID AS \"transacaoOriginalId\", ")
					.append("EI.ICMS as \"icmsBase\", EST.ESTADO_ID as \"estadoId\", ")
					.append("CASE WHEN C.PTOVTAVENTA_ID = :puntoventaId OR C.PTOVTAVENTA_ID IS NULL THEN 1 ELSE 0 END AS ptoVtaOrigem, ")
					.append("M.EMPRESA_ID AS empresaId, C.TRANSACAO_ID AS \"transacaoId\", ")
					.append("CASE WHEN LOG.CONFERENCIA_ID IS NOT NULL OR ")
					.append("		   (C.INDSTATUSBOLETO = 'E' ")
					.append("		   AND LOG.LOGCONFERENCIA_ID IS NULL ")
					.append("		   AND (SELECT LC.LOGCONFERENCIA_ID FROM LOG_CONFERENCIA LC ")
					.append("		   		WHERE LC.ACTIVO = 1 ")
					.append("		   		AND LC.TRANSACAOORIGINAL_ID = C.TRANSACAOORIGINAL_ID ")
					.append("		   		AND LC.LOGCONFERENCIA_ID <> LOG.LOGCONFERENCIA_ID) IS NOT NULL) ")
					.append("		   THEN 1 ELSE 0 END AS \"conferidoEntrega\", ")
					.append("C.PTOVTAVENTA_ID AS ptovtaventaId, ")
					.append("C.PUNTOVENTA_ID AS puntoventaId ")
					.append(", CF.cajaformapago_id, U.USUARIO_ID usuarioId, C.TURNO_ID as turnoId ") //Mantis 17018
					.append("FROM CAJA C ")
					.append("LEFT JOIN PARADA ORI ON ORI.PARADA_ID = C.ORIGEN_ID ")
					.append("LEFT JOIN CIUDAD CID ON CID.CIUDAD_ID = ORI.CIUDAD_ID ")
					.append("LEFT JOIN ESTADO EST ON EST.ESTADO_ID = CID.ESTADO_ID ")
					.append("LEFT JOIN CATEGORIA CAT ON CAT.CATEGORIA_ID = C.CATEGORIA_ID ")
					.append("LEFT JOIN CORRIDA_TRAMO CT ON CT.CORRIDA_ID = C.CORRIDA_ID AND CT.FECCORRIDA = C.FECCORRIDA AND CT.ORIGEN_ID = C.ORIGEN_ID AND CT.DESTINO_ID = C.DESTINO_ID ")
					.append("LEFT JOIN LOG_CONFERENCIA LOG ON LOG.CAJA_ID = C.CAJA_ID AND LOG.ACTIVO = 1 ")
					.append("LEFT JOIN MOTIVO_CANCELACION MC ON MC.MOTIVOCANCELACION_ID = C.MOTIVOCANCELACION_ID ")
					.append("INNER JOIN CAJA_FORMAPAGO CF ON CF.CAJA_ID = C.CAJA_ID ")
					.append("INNER JOIN FORMA_PAGO FP ON FP.FORMAPAGO_ID = CF.FORMAPAGO_ID ")
					.append("INNER JOIN USUARIO U ON C.USUARIO_ID = U.USUARIO_ID ")
					.append("INNER JOIN MARCA M ON C.MARCA_ID = M.MARCA_ID ")
					.append("INNER JOIN EMPRESA E ON E.EMPRESA_ID = M.EMPRESA_ID ")
					.append("LEFT JOIN EMPRESA_IMPOSTO EI ON (EI.ESTADO_ID = EST.ESTADO_ID AND EI.EMPRESA_ID = E.EMPRESA_ID AND EI.ACTIVO = 1) ")
					.append("LEFT JOIN COM_EMP_FORMAPAGO COMFP ON COMFP.FORMAPAGO_ID = FP.FORMAPAGO_ID AND COMFP.EMPRESA_ID = M.EMPRESA_ID AND COMFP.ACTIVO = 1 ")
					.append("LEFT JOIN TARIFA T ON (T.DESTINO_ID = C.DESTINO_ID AND T.CLASESERVICIO_ID = C.CLASESERVICIO_ID AND T.MARCA_ID = M.MARCA_ID AND T.ORIGEN_ID = C.ORIGEN_ID AND T.RUTA_ID = C.RUTA_ID and T.ACTIVO = 1 and (ct.tramo_id = t.tramo_id)) ")
					.append("LEFT JOIN VIGENCIA_TARIFA VT ON (VT.VIGENCIATARIFA_ID = T.VIGENCIATARIFA_ID ) ")
					.append("WHERE C.ACTIVO = 1 AND (T.TARIFA_ID IS NULL OR (T.TARIFA_ID IS NOT NULL  AND C.FECHORVENTA BETWEEN VT.FECINICIOVIGENCIA AND VT.FECFINVIGENCIA)) ")
					.append("AND C.FECCORTE BETWEEN TO_DATE(:dataInicial, 'DD/MM/YYYY') AND TO_DATE(:dataFinal, 'DD/MM/YYYY') ")
					.append("AND ((C.INDSTATUSBOLETO = 'E' AND C.INDREIMPRESION = 1) OR C.INDREIMPRESION = 0 OR C.MOTIVOCANCELACION_ID = :motivoCancelacionGeracaoOcd) ");
			parametros.put("motivoCancelacionGeracaoOcd", Constantes.MVO_CANCEL_GERACAO_OCD.intValue());
			
			if (parametros.containsKey("empresaId")) {
				sQuery.append("AND M.EMPRESA_ID = :empresaId ");
			}
			
			if (parametros.containsKey("puntoventaId")) {
				if (isCalculoComissao && isConsideraBilhetesDevolvidosEmOutraAgencia){
					String sMotivosCancelacion = Arrays.asList(
							Constantes.MVO_CANCEL_DEVOLUCAO.intValue(),
							Constantes.MVO_CANCEL_DEVOLUCAO_CONTIGENCIA_100.intValue(),
							Constantes.MVO_CANCEL_DEVOLUCAO_CONTIGENCIA_50.intValue(),
							Constantes.MVO_CANCEL_CANCELACION.intValue(),
							Constantes.MVO_CANCEL_GERACAO_OCD.intValue(),
							Constantes.MVO_CANCEL_TROCA.intValue(),
							Constantes.MVO_CANCEL_TRANSFERENCIA.intValue()
							).toString().replaceAll("[\\[\\]]", "");
					
					sQuery.append("AND ( ")
						  /* Filtra pela agencias, com a operação feita na agencia ou que tenha origem na agencia de filtro */
						  .append("     ( ")
						  .append("       ((C.PUNTOVENTA_ID = :puntoventaId AND C.PTOVTAVENTA_ID IS NULL) OR C.PTOVTAVENTA_ID = :puntoventaId) ")
						  .append("       AND ")
						  /* Filtro os não cancelados e os cancelados conforme lista de motivos de cancelamentos aceitos */
						  .append("       ( ")
						  .append("      	C.MOTIVOCANCELACION_ID IS NULL  ")
						  .append("      	OR  ")
						  .append("      	C.MOTIVOCANCELACION_ID IN (").append(sMotivosCancelacion).append(") ")
						  .append("       )  ")
						  .append("     ) ")
						  /* Carrega os bilhetes entregues na agencia */
						  .append("		OR ")
						  .append("		(C.PUNTOVENTA_ID = :puntoventaId AND C.INDSTATUSBOLETO = 'E' AND C.MOTIVOCANCELACION_ID IS NULL) ")
						  .append(" ) ");
				}else{
					sQuery.append("AND C.PUNTOVENTA_ID = :puntoventaId ");
				}
			}
			if (StringUtils.isNotBlank(conferencia.getNumfoliosistema())) {
				sQuery.append("AND C.NUMFOLIOSISTEMA = :numfoliosistema ");
				parametros.put("numfoliosistema", conferencia.getNumfoliosistema());
			}
			sQuery.append("ORDER BY C.INDSTATUSBOLETO, C.MOTIVOCANCELACION_ID, C.CAJA_ID ");
			
			con = getConnection();
			npst = new NamedParameterStatement(con, sQuery.toString());
			setParametros(npst, parametros);
			npst.setFetchSize(100);
			rSet = npst.executeQuery();

			List<BoletoComissao> lsBoletoComissao = new ArrayList<BoletoComissao>();
			while(rSet.next()) {
				BoletoComissao boletoComissao = new BoletoComissao();
				boletoComissao.setCajaId(rSet.getLong("cajaId"));
				boletoComissao.setTransacaoOriginalId(rSet.getLong("transacaoOriginalId") > 0 ? rSet.getLong("transacaoOriginalId") : null );
				boletoComissao.setNumAsiento(rSet.getString("numAsiento"));
				boletoComissao.setNumAsientoVinculado(rSet.getString("numAsientoVinculado"));
				boletoComissao.setNumFolioSistema(rSet.getString("numFolioSistema"));
				boletoComissao.setNumSeriePreimpresa(rSet.getString("numSeriePreimpresa"));
				boletoComissao.setNumFolioPreImpreso(rSet.getString("numFolioPreImpreso"));
				boletoComissao.setUf(rSet.getString("uf"));
				boletoComissao.setDesccategoria(rSet.getString("desccategoria"));
				boletoComissao.setValorpagado(rSet.getBigDecimal("valorpagado"));
				boletoComissao.setValorTabela(rSet.getBigDecimal("valorTabela"));
				boletoComissao.setSeguroOutros(rSet.getBigDecimal("seguroOutros"));
				boletoComissao.setPedagio(rSet.getBigDecimal("pedagio"));
				boletoComissao.setEmbarque(rSet.getBigDecimal("embarque"));
				boletoComissao.setSeguro(rSet.getBigDecimal("seguro"));
				boletoComissao.setTipoVenta(rSet.getInt("tipoVenta"));
				boletoComissao.setIndstatusboleto(rSet.getString("indstatusboleto"));
				boletoComissao.setStatus(rSet.getInt("status") >= 0 ? rSet.getInt("status") : null);
				boletoComissao.setFormapagoId(rSet.getInt("formapagoId") > 0 ? rSet.getInt("formapagoId") : null);
				boletoComissao.setDescpago(rSet.getString("descpago"));
				boletoComissao.setLogconferenciaId(rSet.getLong("logconferenciaId") > 0 ? rSet.getLong("logconferenciaId") : null);
				boletoComissao.setDescmotivocancelacion(rSet.getString("descmotivocancelacion"));
				boletoComissao.setNombusuario(rSet.getString("nombusuario"));
				boletoComissao.setMotivoCancelacionId(rSet.getInt("motivoCancelacionId") > 0 ? rSet.getInt("motivoCancelacionId") : null);
				boletoComissao.setImporteFp(rSet.getBigDecimal("importeFp"));
				boletoComissao.setComempformapagoId(rSet.getInt("comempformapagoId") > 0 ? rSet.getInt("comempformapagoId") : null);
				boletoComissao.setComempcategoriaId(rSet.getInt("comempcategoriaId") > 0 ? rSet.getInt("comempcategoriaId") : null);
				boletoComissao.setNumoperacion(rSet.getString("numoperacion"));
				boletoComissao.setNombpasajero(rSet.getString("nombpasajero"));
				boletoComissao.setIndcarboletosdevolvidosconf(rSet.getBoolean("indcarboletosdevolvidosconf"));
				boletoComissao.setFeccorrida(rSet.getDate("feccorrida"));
				boletoComissao.setCorridaId(rSet.getInt("corridaId") > 0 ? rSet.getInt("corridaId") : null);
				boletoComissao.setIndCancelacion(rSet.getBoolean("indCancelacion"));
				boletoComissao.setIndreimpresion(rSet.getBoolean("indreimpresion"));
				boletoComissao.setFeccorte(rSet.getDate("feccorte"));
				boletoComissao.setIcmsBase(rSet.getBigDecimal("icmsBase"));
				boletoComissao.setEstadoId(rSet.getInt("estadoId") > 0 ? rSet.getInt("estadoId") : null);
				boletoComissao.setPtoVtaOrigem(rSet.getBoolean("ptoVtaOrigem"));
				boletoComissao.setValorbase(rSet.getBigDecimal("valorbase"));
				boletoComissao.setEmpresaId(rSet.getInt("empresaId"));
				boletoComissao.setTransacaoId(rSet.getLong("transacaoId") > 0 ? rSet.getLong("transacaoId") : null);
				boletoComissao.setPtovtaventaId(rSet.getInt("ptovtaventaId"));
				boletoComissao.setPuntoVentaId(rSet.getInt("puntoventaId"));
				boletoComissao.setConferidoEntrega(rSet.getBoolean("conferidoEntrega"));
				boletoComissao.setUsuarioId(rSet.getInt("usuarioId"));
				boletoComissao.setTurnoId(rSet.getInt("turnoId"));
					
				if(boletoComissao.getStatus() == null && boletoComissao.getConferidoEntrega() != null && boletoComissao.getConferidoEntrega()) {
					boletoComissao.setConferido(true);
					boletoComissao.setStatus(StatusLogConferencia.CONFERIDO.getValue());
				}
			
				if (boletoComissao.getFormapagos() == null) {
					boletoComissao.setFormapagos(new ArrayList<FormapagoVO>());
					boletoComissao.setConferencia(conferencia);
				}
				if(boletoComissao.getImporteFp() == null){
					boletoComissao.setImporteFp(BigDecimal.ZERO);
				}

				if (lsBoletoComissao.contains(boletoComissao)) {
					int indice = lsBoletoComissao.indexOf(boletoComissao);
					BoletoComissao aux = lsBoletoComissao.get(indice);
					aux.setComempcategoriaId(boletoComissao.getComempcategoriaId() != null
							? boletoComissao.getComempcategoriaId() : aux.getComempcategoriaId());
					aux.setComempformapagoId(boletoComissao.getComempformapagoId() != null
							? boletoComissao.getComempformapagoId() : aux.getComempformapagoId());

					FormapagoVO formapagoVO = new FormapagoVO(boletoComissao.getFormapagoId(),
							boletoComissao.getDescpago(),
							boletoComissao.getIndconferenciafisicacomissao(),
							boletoComissao.getImporteFp());

					if (aux.getFormapagos().contains(formapagoVO)) {
						formapagoVO = aux.getFormapagos().get(aux.getFormapagos().indexOf(formapagoVO));
						formapagoVO.add(boletoComissao.getImporteFp());
					} else {
						aux.getFormapagos().add(formapagoVO);
					}
					lsBoletoComissao.set(indice, aux);
				} else {
					boletoComissao.getFormapagos().add(new FormapagoVO(boletoComissao.getFormapagoId(),
							boletoComissao.getDescpago(),
							boletoComissao.getIndconferenciafisicacomissao(),
							boletoComissao.getImporteFp()));
					lsBoletoComissao.add(boletoComissao);
				}
			}
			
			return lsBoletoComissao;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		} finally {
			try {
				if(rSet != null && !rSet.isClosed()) {
					rSet.close();
				}
				if(npst != null && !npst.isClosed()) {
					npst.close();
				}
				if(con != null && !con.isClosed()) {
					con.close();
				}
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
	}

	@Override
	public List<OcdVO> carregarOcds(Conferencia conferencia) throws BusinessException {
		
		Connection con = null;
		NamedParameterStatement npst = null;
		ResultSet rSet = null;
		
		try {
			Map<String, Object> parametros = carregarParametros(null, null, null, conferencia.getEmpresa(),
					conferencia.getPuntoVenta(), conferencia.getDatamovimento(), false);

			StringBuilder sQuery = new StringBuilder()
					.append("SELECT DISTINCT O.OCD_ID AS \"ocdId\", O.NUMOPERACION AS \"numoperacion\", O.FECINC AS \"fecinc\", O.FECPAGAR AS \"fecpagar\", O.FECPAGO AS \"fecpago\", ")
					.append("O.INDPAGO AS \"indpago\", O.VALOR_PAGAR AS \"valorPagar\", (B.PRECIOPAGADO * (O.PENALIZACION / 100)) AS \"penalizacion\", NVL(LOG.STATUS,-1) AS \"status\", ")
					.append("U.NOMBUSUARIO AS \"nombusuario\", LOG.LOGCONFERENCIA_ID AS \"logconferenciaId\", U.CVEUSUARIO AS \"login\", B.NUMFOLIOSISTEMA AS \"numFolioSistema\", ")
					.append("CEC.INDOCD AS \"exigeConferenciaAba\" ")
					.append("FROM OCD O ")
					.append("INNER JOIN BOLETO B ON B.BOLETO_ID = O.BOLETO_ID ")
					.append("INNER JOIN MARCA M ON B.MARCA_ID = M.MARCA_ID ")
					.append("LEFT JOIN LOG_CONFERENCIA LOG ON LOG.OCD_ID = O.OCD_ID AND LOG.ACTIVO = 1 ")
					.append("INNER JOIN USUARIO U ON O.USUARIOPAGO_ID = U.USUARIO_ID ")
					.append("LEFT JOIN COM_EMP_CONFERENCIA CEC ON CEC.EMPRESA_ID = M.EMPRESA_ID AND CEC.ACTIVO = 1 ")
					.append("INNER JOIN MARCA ON m.MARCA_ID = b.MARCA_ID ")
					.append("WHERE O.ACTIVO = 1 ")
					.append("AND O.FECPAGO BETWEEN TO_DATE(:dataInicial, 'DD/MM/YYYY HH24:MI') AND TO_DATE(:dataFinal, 'DD/MM/YYYY HH24:MI') ")
					.append("AND O.INDPAGO = 1 ");

			if (parametros.containsKey("empresaId")) {
				sQuery.append("AND ((B.EMPRESACORRIDA_ID IS NOT NULL AND B.EMPRESACORRIDA_ID = :empresaId) OR(m.EMPRESA_ID = :empresaId)) ");
			}
			if (parametros.containsKey("puntoventaId")) {
				sQuery.append("AND O.PUNTOVENTAPAGO_ID = :puntoventaId ");
			}
			
			con = getConnection();
			npst = new NamedParameterStatement(con, sQuery.toString());
			setParametros(npst, parametros);
			rSet = npst.executeQuery();
			
			List<OcdVO> result = new ArrayList<OcdVO>();
			while(rSet.next()) {
				OcdVO ocd = new OcdVO();
				ocd.setOcdId(rSet.getLong("ocdId"));
				ocd.setNumoperacion(rSet.getString("numoperacion"));
				ocd.setFecinc(rSet.getDate("fecinc"));
				ocd.setFecpagar(rSet.getDate("fecpagar"));
				ocd.setFecpago(rSet.getDate("fecpago"));
				ocd.setIndpago(rSet.getBoolean("indpago"));
				ocd.setValorPagar(rSet.getBigDecimal("valorPagar"));
				ocd.setPenalizacion(rSet.getBigDecimal("penalizacion"));
				ocd.setStatus(rSet.getInt("status") >= 0 ? rSet.getInt("status") : null);
				ocd.setLogconferenciaId(rSet.getLong("logconferenciaId") > 0 ? rSet.getLong("logconferenciaId") : null);
				ocd.setLogin(rSet.getString("login"));
				ocd.setNombusuario(rSet.getString("nombusuario"));
				ocd.setNumFolioSistema(rSet.getString("numFolioSistema"));
				ocd.setExigeConferenciaAba(rSet.getBoolean("exigeConferenciaAba"));
				ocd.setConferencia(conferencia);
				
				result.add(ocd);
			}

			return result;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		} finally {
			try {
				if(rSet != null && !rSet.isClosed()) {
					rSet.close();
				}
				if(npst != null && !npst.isClosed()) {
					npst.close();
				}
				if(con != null && !con.isClosed()) {
					con.close();
				}
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
	}

	@Override
	public Conferencia obtenerConferenciaDataMovimento(Date datamovimento, Integer puntoventaId,
			Integer empresaId) throws BusinessException {
		try {
			StringBuilder sQuery = new StringBuilder()
					.append("SELECT co ").append("FROM Conferencia co ")
					.append("WHERE co.activo = 1 ").append("AND co.datamovimento = :datamovimento ")
					.append("AND co.empresa.empresaId = :empresaId ")
					.append("AND co.puntoVenta.puntoventaId = :puntoventaId ");

			Query qr = getSession().createQuery(sQuery.toString());
			qr.setParameter("datamovimento", datamovimento);
			qr.setParameter("empresaId", empresaId);
			qr.setParameter("puntoventaId", puntoventaId);
			qr.setMaxResults(1);
			return (Conferencia) qr.uniqueResult();

		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	@Transactional
	private void gerarLancamentoContaCorrente(Conferencia conferencia) throws BusinessException {
		try {

			Calendar calHoje = Calendar.getInstance();
			Calendar calAmanha = Calendar.getInstance();

			calAmanha.add(Calendar.DAY_OF_MONTH, 1);

			List<LogConferencia> lsLogConferencia = carregarLogConferencia(conferencia.getConferenciaId());
			String sDataMovimento = DateUtil.getStringDate(conferencia.getDatamovimento(), "dd/MM/yyyy");
			String descOperacion = "CONFERENCIA MOVIMENTO DIA - " + sDataMovimento;

			for (LogConferencia logConferencia : lsLogConferencia) {
				Calendar cal = calHoje;

				if (!Boolean.TRUE.equals(logConferencia.getIndmesmodia())) {
					cal = calAmanha;
				}

				if (logConferencia.getStatus().equals(StatusLogConferencia.CONFERIDO)
						|| ((logConferencia.getContaCorrentePtoVta() != null
								&& logConferencia.getContaCorrentePtoVta().getActivo() != null
								&& logConferencia.getContaCorrentePtoVta().getActivo()))
						|| (logConferencia.getPreco() == null
								|| logConferencia.getPreco().doubleValue() == 0d)
						|| logConferencia.isIndcredito().equals((short) 2)) {
					continue;
				}

				ContaCorrentePtoVta contaCorrentePtoVta = contaCorrenteAgenciaDAO
						.gravarContaCorrente(conferencia.getPuntoVenta().getPuntoventaId(),
								descOperacion, DateUtil.normalizarToFecha(cal.getTime()), logConferencia.getUsuario().getUsuarioId(),
								logConferencia.isIndcredito().equals((short) 1) ? Constantes.TIPO_OPERACION_CC_PAGO : Constantes.TIPO_OPERACION_CC_LQ,
								conferencia.getEmpresa().getEmpresaId(),
								Constantes.TURNO_AUTOMATICO, BigDecimal.ZERO, BigDecimal.ZERO,
								BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO,
								BigDecimal.ZERO, BigDecimal.ZERO, logConferencia.getPreco(), false,
								BigDecimal.ZERO, BigDecimal.ZERO, logConferencia.getPreco());

				logConferencia.setContaCorrentePtoVta(contaCorrentePtoVta);
				suscribirLogConferencia(logConferencia);
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<LogConferencia> carregarLogConferencia(Long conferenciaId) throws BusinessException {
		try {
			StringBuilder sQuery = new StringBuilder()
					.append("SELECT log ")
					.append("FROM LogConferencia log ")
					.append("WHERE log.activo = 1 ")
					.append("AND log.conferencia.conferenciaId = :conferenciaId ");
			Query qr = getSession().createQuery(sQuery.toString());
			qr.setParameter("conferenciaId", conferenciaId);
			return qr.list();
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	@Override
	public boolean isConferenciaCompetenciaEncerrada(String competencia, Empresa empresa,
			PuntoVenta puntoVenta, boolean isDesconsideraPtVendaFechados) throws BusinessException {
		try {
			List<ConferenciaComissaoVO> lsConferencias = new ArrayList<ConferenciaComissaoVO>();

			carregarConferenciasRegistradas(lsConferencias, competencia, empresa, puntoVenta, null, null, null, null);
			carregarDiasSemMovimento(lsConferencias, competencia, empresa, puntoVenta, null);

			for (ConferenciaComissaoVO conferenciaComissao : lsConferencias) {
				for (DiaConferenciaComissaoVO diaConferenciaComissao : conferenciaComissao.getDias()) {
					if (!diaConferenciaComissao.getIndsemmovimento() && !diaConferenciaComissao.getIndconferido()) {
						return false;
					}
				}
			}

			return true;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	@Override
	public BigDecimal carregarValorDepositoContaCorrente(Integer empresaId, Integer puntoventaId, Date datamovimento) {
		StringBuilder sQuery = new StringBuilder()
				.append("SELECT SUM(importeTotalEfectivo) ").append("FROM ContaCorrentePtoVta cc ")
				.append("WHERE cc.activo = 1 ").append("AND cc.empresa.empresaId = :empresaId ")
				.append("AND cc.puntoVenta.puntoventaId = :puntoventaId ")
				.append("AND cc.fecHorOperacion = :datamovimento ");

		Query qr = getSession().createQuery(sQuery.toString());
		qr.setParameter("empresaId", empresaId);
		qr.setParameter("puntoventaId", puntoventaId);
		qr.setParameter("datamovimento", datamovimento);
		qr.setMaxResults(1);

		return (BigDecimal) qr.uniqueResult();
	}

	@Override
	@SuppressWarnings("unchecked")
	public DiaConferenciaComissaoVO carregarConferenciaRegistrada(Date datamovimento,
			Empresa empresa, PuntoVenta puntoVenta) throws BusinessException {
		try {
			String competencia = DateUtil.getStringDate(datamovimento, "MM/yyyy");
			Map<String, Object> parametros = carregarParametros(null, null, competencia, empresa, puntoVenta, datamovimento, false);
			StringBuilder sQuery = new StringBuilder("SELECT co FROM Conferencia co ")
					.append("JOIN co.empresa em ").append("JOIN co.puntoVenta pv ")
					.append("WHERE co.activo = 1 ")
					.append("AND co.datamovimento BETWEEN TO_DATE(:dataInicial,'DD/MM/YYYY HH24:MI') AND TO_DATE(:dataFinal,'DD/MM/YYYY HH24:MI') ");

			if (parametros.containsKey("empresaId")) {
				sQuery.append("AND em.empresaId = :empresaId ");
			}
			if (parametros.containsKey("puntoventaId")) {
				sQuery.append("AND pv.puntoventaId = :puntoventaId ");
			}

			Query qr = getSession().createQuery(sQuery.toString());
			setParametros(qr, parametros);

			List<ConferenciaComissaoVO> lsConferenciaComissao = new ArrayList<ConferenciaComissaoVO>();
			processarQueryConferencia(qr.list(), lsConferenciaComissao, competencia, datamovimento, null, null);

			if (!lsConferenciaComissao.isEmpty()) {
				for (DiaConferenciaComissaoVO diaConferenciaComissao : lsConferenciaComissao
						.iterator().next().getDiasOrdenado()) {
					if (diaConferenciaComissao.getData().equals(datamovimento)) {
						return diaConferenciaComissao;
					}
				}
			}

			return null;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	/**
	 * Recupera a conexão conforme parametrização em application.properties
	 * 
	 * @return
	 * @throws SQLException
	 */
	public Connection getConnection() throws SQLException {
		if (ApplicationProperties.getInstance().isCustomHabilitado(CustomEnum.IS_DATASOURCE_COMISSAO_BANCO_PRODUCAO.getDescricao())) {
			return dataSource.getConnection();
		} else {
			return dataSourceRead.getConnection();
		}
	}

	@Override
	public boolean isConferidoVenta(BoletoComissao boletoComissao) {
		if(boletoComissao.getTransacaoOriginalId() == null ){
			return false;
		}

		StringBuilder sql = new StringBuilder();

		sql.append(" SELECT * FROM  log_conferencia lc ");
		sql.append(" WHERE lc.ACTIVO = 1 ");
		sql.append(" AND lc.TRANSACAOORIGINAL_ID =:transacaoId ");

		Query qr = getSession().createSQLQuery(sql.toString());
		qr.setParameter("transacaoId", boletoComissao.getTransacaoOriginalId());

		return !qr.list().isEmpty();

	}
	
	@Override
	@SuppressWarnings("unchecked")
	@Transactional
	public void borrarLogConferenciaTransacaoId(Long transacaoId) throws BusinessException {
		try {
			StringBuilder sql = new StringBuilder();

			sql.append("SELECT log ")
			   .append("FROM LogConferencia log ")
			   .append("WHERE log.activo = 1 ")
			   .append("AND log.transacaoOriginalId =:transacaoId ");

			Query qr = getSession().createQuery(sql.toString());
			qr.setParameter("transacaoId", transacaoId);
			
			List<LogConferencia> logConferencias = qr.list();
			for (LogConferencia logConferencia : logConferencias) {
				borrarLogConferencia(logConferencia);
			}			
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	@Override
	public boolean isConferenciaCompetenciaEncerrada(Date dataInicial, Date dataFinal, Empresa empresa, PuntoVenta puntoVenta, boolean isDesconsideraPtVendaFechados) throws BusinessException {
		try {
			List<ConferenciaComissaoVO> lsConferencias = new ArrayList<ConferenciaComissaoVO>();

			String competencia = DateUtil.getStringDate(dataInicial, "MM/yyyy");
			
			carregarConferenciasRegistradas(lsConferencias, competencia, empresa, puntoVenta, null, dataInicial, dataFinal, null);
			carregarDiasSemMovimento(lsConferencias, competencia, empresa, puntoVenta, null);

			for (ConferenciaComissaoVO conferenciaComissao : lsConferencias) {
				for (DiaConferenciaComissaoVO diaConferenciaComissao : conferenciaComissao.getDias()) {
					if (DateUtil.compareOnlyDate(diaConferenciaComissao.getData(), dataInicial) >= 0 &&
						DateUtil.compareOnlyDate(diaConferenciaComissao.getData(), dataFinal) <= 0 &&
						!diaConferenciaComissao.getIndsemmovimento() && !diaConferenciaComissao.getIndconferido()) {
						return false;
					}
				}
			}

			return true;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage(), e);
		}
	}

	@Override
	public boolean isConfMovFPTrocaVlrDeposito(Empresa empresa) {
		if(empresa == null || empresa.getEmpresaId() == null) {
			return false;
		}
		
		StringBuilder sql = new StringBuilder();
		sql.append(" SELECT EMPRESA_ID ")
		   .append(" FROM EMPRESA ")
		   .append(" WHERE ACTIVO = 1 ")
		   .append(" AND INDCONFMOVFPTROCAVLRDEPOSITO = 1 ")
		   .append(" AND EMPRESA_ID = :empresaId ");

		Query qr = getSession().createSQLQuery(sql.toString());
		qr.setParameter("empresaId", empresa.getEmpresaId());

		return !qr.list().isEmpty();
	}

	@Override
	public BigDecimal getComissaoPuntoVenta(Integer puntoventaId, Integer empresaId, Date dataInicial, Date dataFinal) throws BusinessException {
		StringBuilder sql = new StringBuilder();
		sql.append(" SELECT SUM(importe) ")
		   .append(" FROM conta_corrente_ptovta ")
		   .append(" WHERE ACTIVO = 1 ")
		   .append(" AND EMPRESA_ID = :empresaId ")
		   .append(" AND PUNTOVENTA_ID = :puntoventaId ")
		   .append(" AND TIPOOPERACIONCC_ID = 5 ")
		   .append(" AND feccorte BETWEEN to_date(:dataInicial, 'DD/MM/YYYY') AND to_date(:dataFinal, 'DD/MM/YYYY') ");


		Query qr = getSession().createSQLQuery(sql.toString());
		qr.setParameter("empresaId", empresaId);
		qr.setParameter("puntoventaId", puntoventaId);
		qr.setParameter("dataInicial", DateUtil.getStringDate(DateUtil.inicioFecha(dataInicial), "dd/MM/yyyy"));
		qr.setParameter("dataFinal", DateUtil.getStringDate(DateUtil.inicioFecha(dataFinal), "dd/MM/yyyy"));
		
		return (BigDecimal) qr.uniqueResult();
	}
}
