package com.rjconsultores.ventaboletos.dao.hibernate;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.transform.Transformers;
import org.hibernate.type.BigDecimalType;
import org.hibernate.type.IntegerType;
import org.hibernate.type.StringType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

import com.rjconsultores.ventaboletos.constantes.Constantes;
import com.rjconsultores.ventaboletos.dao.CategoriaDescuentoDAO;
import com.rjconsultores.ventaboletos.dao.OperadorEmbarcadaServicoDAO;
import com.rjconsultores.ventaboletos.dao.util.DBUtil;
import com.rjconsultores.ventaboletos.entidad.AliasServico;
import com.rjconsultores.ventaboletos.entidad.CategoriaDescuento;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.OperadorEmbarcada;
import com.rjconsultores.ventaboletos.entidad.OperadorEmbarcadaServico;
import com.rjconsultores.ventaboletos.entidad.PuntoVenta;
import com.rjconsultores.ventaboletos.entidad.TarifaMinima;
import com.rjconsultores.ventaboletos.service.AliasServicoService;
import com.rjconsultores.ventaboletos.vo.corrida.CorridaVO;
import com.rjconsultores.ventaboletos.vo.corrida.TramoSequenciaVO;
import com.rjconsultores.ventaboletos.vo.parada.ParadaVO;
import com.rjconsultores.ventaboletos.vo.roloperativo.RolOperativoVO;
import com.rjconsultores.ventaboletos.vo.secuencia.SecuenciaVO;
import com.rjconsultores.ventaboletos.vo.tiposervicio.TipoServicioVO;
import com.rjconsultores.ventaboletos.vo.tramo.TramoVO;
import com.rjconsultores.ventaboletos.vo.via.ViaVO;

@Repository("operadorEmbarcadaServicoDAO")
@SuppressWarnings({"unchecked", "rawtypes"})
public class OperadorEmbarcadaServicoHibernateDAO extends GenericHibernateDAO<OperadorEmbarcadaServico, Long> implements OperadorEmbarcadaServicoDAO {

	private static final Logger log = LogManager.getLogger(OperadorEmbarcadaServicoHibernateDAO.class);
	
	@Autowired
	private CategoriaDescuentoDAO categoriaDescuentoDAO;
	
	@Autowired
	private ConstanteHibernateDAO constanteDAO;

	@Autowired
	private AliasServicoService aliasServicoService;

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

	@Override
	public List<OperadorEmbarcadaServico> buscarPorOperador(OperadorEmbarcada operador) {
		StringBuilder sb = new StringBuilder();
        sb.append(" from OperadorEmbarcadaServico oes ");
        sb.append(" where oes.operadorEmbarcada.operadorEmbarcadaId = :operadorEmbarcadaId ");
        sb.append("   and oes.activo = 1 ");

        Query query = getSession().createQuery(sb.toString());
        query.setLong("operadorEmbarcadaId", operador.getOperadorEmbarcadaId());
        return query.list();
	}

	@Override
	public List<CorridaVO> getListaCorridaVO(Integer operador, Empresa empresa, Date dtIni, Date dtFim, PuntoVenta puntoVenta) {
		List<CorridaVO> corridas = getCorridas(operador, empresa, dtIni, dtFim);

		for (CorridaVO corrida : corridas) {
			preencherTramosSequencias(corrida, puntoVenta, empresa);
			preencherSequencias(corrida);
		}

		return corridas;
	}
	
	@Override
	public List getListaResumidaCorridaVO(Integer operador, Empresa empresa, Date dtIni, Date dtFim, PuntoVenta puntoVenta, Boolean retornaTramos ) throws Exception {
		return getCorridasResumido(operador, empresa, dtIni, dtFim, retornaTramos);
	}

	@Override
	public List<CorridaVO> getListaCorridaProxyVO(Integer operador, Empresa empresa, Date dtIni, Date dtFim) {
		return getCorridas(operador, empresa, dtIni, dtFim);
	}

	@Override
	public void preencherCorrida(CorridaVO corrida, PuntoVenta puntoVenta, Empresa empresa) {
		preencherTramosSequencias(corrida, puntoVenta, empresa);
		preencherSequencias(corrida);
	}

	private List<CorridaVO> getCorridas(Integer operador, Empresa empresa, Date dtIni, Date dtFim) {
		StringBuilder sb = new StringBuilder();

		sb.append("select * from (SELECT");
		sb.append(" 	COR.CORRIDA_ID         AS CORRIDAID,");
		sb.append(" 	ESQ.NUMCORRIDA         AS NUMCORRIDA,");
		sb.append(" 	''                     AS DESCSERVICO,");
		sb.append(" 	COR.FECHORSALIDA       AS FECHORSALIDA,");
		sb.append(" 	COR.TIPOSERVICIO_ID    AS TIPOSERVICIOID,");
		sb.append(" 	TPS.DESCSERVICIO       AS DESCSERVICIO,");
		sb.append(" 	ROL.ROLOPERATIVO_ID    AS ROLOPERATIVOID,");
		sb.append(" 	ROL.DESCROLOPERATIVO   AS DESCROLOPERATIVO,");
		sb.append(" 	COR.RUTA_ID            AS RUTA_ID,");
		sb.append(" 	COR.ORIGEN_ID          AS ORIGEMID,");
		sb.append(" 	ORI.DESCPARADA         AS DESCORIGEM,");
		sb.append(" 	COR.DESTINO_ID         AS DESTINOID,");
		sb.append(" 	DES.DESCPARADA         AS DESCDESTINO,");
		sb.append(" 	ORIEST.CVEESTADO       AS ORICVEESTADO,");
		sb.append(" 	DESEST.CVEESTADO       AS DESCVEESTADO,");
		sb.append(" 	COR.CLASESERVICIO_ID   AS CLASESERVICIO_ID,");
		sb.append(" 	COR.MARCA_ID   		   AS MARCA_ID,");
		sb.append(" 	to_char(COR.FECCORRIDA, 'dd/MM/YYYY') AS FECCORRIDA,");
		sb.append(" 	COR.EMPRESACORRIDA_ID   	   AS EMPRESA_ID");
		sb.append(" FROM OPERADOR_EMBARCADA OPE");
		sb.append(" JOIN OPERADOR_EMBARCADA_SERVICO OPS ON OPE.OPERADOR_EMBARCADA_ID = OPS.OPERADOR_EMBARCADA_ID");
		sb.append(" JOIN ESQUEMA_CORRIDA ESQ ON ESQ.ESQUEMACORRIDA_ID = OPS.ESQUEMA_CORRIDA_ID");
		sb.append(" JOIN CORRIDA COR ON COR.ESQUEMACORRIDA_ID = ESQ.ESQUEMACORRIDA_ID");
		sb.append(" JOIN TIPO_SERVICIO TPS ON COR.TIPOSERVICIO_ID = TPS.TIPOSERVICIO_ID");
		sb.append(" JOIN ROL_OPERATIVO ROL ON COR.ROLOPERATIVO_ID = ROL.ROLOPERATIVO_ID");
		sb.append(" JOIN PARADA ORI ON ORI.PARADA_ID = COR.ORIGEN_ID");
		sb.append(" JOIN CIUDAD ORICID ON ORICID.CIUDAD_ID = ORI.CIUDAD_ID");
		sb.append(" JOIN ESTADO ORIEST ON ORIEST.ESTADO_ID = ORICID.ESTADO_ID");
		sb.append(" JOIN PARADA DES ON DES.PARADA_ID = COR.DESTINO_ID");
		sb.append(" JOIN CIUDAD DESCID ON DESCID.CIUDAD_ID = DES.CIUDAD_ID");
		sb.append(" JOIN ESTADO DESEST ON DESEST.ESTADO_ID = DESCID.ESTADO_ID");
		sb.append(" WHERE  OPE.USUARIO_ID = :usuarioId");
		sb.append(" 	AND COR.EMPRESACORRIDA_ID = :empresaId");
		sb.append(" 	AND COR.FECCORRIDA >= :dtIni");
		sb.append(" 	AND COR.FECCORRIDA <= :dtFim");
		sb.append(" 	AND OPS.ACTIVO = 1");
		sb.append(" 	AND OPE.ACTIVO = 1");
		sb.append(" 	AND ESQ.ACTIVO = 1");
		sb.append(" 	AND COR.ACTIVO = 1");
		sb.append(" 	AND TPS.ACTIVO = 1");
		sb.append(" 	AND ROL.ACTIVO = 1");
		sb.append(" 	AND ORI.ACTIVO = 1");
		sb.append(" 	AND DES.ACTIVO = 1");
		sb.append(" 	AND COR.INDSTATUSCORRIDA = 'H' ");
		sb.append(" ORDER BY");
		sb.append(" 	COR.FECHORSALIDA,");
		sb.append(" 	COR.CORRIDA_ID) ");
		sb.append(" UNION select * from (SELECT ");
		sb.append("  	COR.CORRIDA_ID         AS CORRIDAID, ");
		sb.append("  	COR.CORRIDA_ID         AS NUMCORRIDA, ");
		sb.append("  	''                     AS DESCSERVICO, ");
		sb.append("  	COR.FECHORSALIDA       AS FECHORSALIDA, ");
		sb.append("  	COR.TIPOSERVICIO_ID    AS TIPOSERVICIOID, ");
		sb.append("  	TPS.DESCSERVICIO       AS DESCSERVICIO, ");
 		sb.append(" 	ROL.ROLOPERATIVO_ID    AS ROLOPERATIVOID, ");
 		sb.append(" 	ROL.DESCROLOPERATIVO   AS DESCROLOPERATIVO, ");
 		sb.append(" 	COR.RUTA_ID            AS RUTA_ID, ");
 		sb.append(" 	COR.ORIGEN_ID          AS ORIGEMID, ");
 		sb.append(" 	ORI.DESCPARADA         AS DESCORIGEM, ");
 		sb.append(" 	COR.DESTINO_ID         AS DESTINOID, ");
 		sb.append(" 	DES.DESCPARADA         AS DESCDESTINO, ");
  		sb.append("		ORIEST.CVEESTADO       AS ORICVEESTADO, ");
  		sb.append("		DESEST.CVEESTADO       AS DESCVEESTADO, ");
  		sb.append("		COR.CLASESERVICIO_ID   AS CLASESERVICIO_ID, ");
 		sb.append(" 	COR.MARCA_ID   		   AS MARCA_ID, ");
 		sb.append(" 	to_char(COR.FECCORRIDA, 'dd/MM/YYYY') AS FECCORRIDA, ");
		sb.append(" 	COR.EMPRESACORRIDA_ID  AS EMPRESA_ID");
 		sb.append(" FROM OPERADOR_EMBARCADA OPE ");
 		sb.append(" JOIN OPERADOR_EMBARCADA_LINHA OPL ON OPE.OPERADOR_EMBARCADA_ID = OPL.OPERADOR_EMBARCADA_ID ");
 		sb.append("  left join operador_embarcada_servico ops on ops.operador_embarcada_id = ope.operador_embarcada_id AND ops.operador_embarcada_servico_id is null");
 		sb.append("  JOIN CORRIDA COR ON COR.ruta_ID = OPL.ruta_ID ");
 		sb.append("  LEFT JOIN ESQUEMA_CORRIDA ESQ ON ESQ.ESQUEMACORRIDA_ID = COR.ESQUEMACORRIDA_ID ");
 		sb.append("  JOIN TIPO_SERVICIO TPS ON COR.TIPOSERVICIO_ID = TPS.TIPOSERVICIO_ID ");
 		sb.append("  JOIN ROL_OPERATIVO ROL ON COR.ROLOPERATIVO_ID = ROL.ROLOPERATIVO_ID ");
 		sb.append("  JOIN PARADA ORI ON ORI.PARADA_ID = COR.ORIGEN_ID ");
 		sb.append("  JOIN CIUDAD ORICID ON ORICID.CIUDAD_ID = ORI.CIUDAD_ID ");
 		sb.append("  JOIN ESTADO ORIEST ON ORIEST.ESTADO_ID = ORICID.ESTADO_ID ");
 		sb.append("  JOIN PARADA DES ON DES.PARADA_ID = COR.DESTINO_ID ");
 		sb.append("  JOIN CIUDAD DESCID ON DESCID.CIUDAD_ID = DES.CIUDAD_ID ");
 		sb.append("  JOIN ESTADO DESEST ON DESEST.ESTADO_ID = DESCID.ESTADO_ID ");
 		sb.append(" WHERE  OPE.USUARIO_ID = :usuarioId");
		sb.append(" 	AND COR.EMPRESACORRIDA_ID = :empresaId");
		sb.append(" 	AND COR.FECCORRIDA >= :dtIni");
		sb.append(" 	AND COR.FECCORRIDA <= :dtFim");
 		sb.append("  	AND OPL.ACTIVO = 1 ");
 		sb.append("  	AND OPE.ACTIVO = 1 ");
 		sb.append("  	AND COR.ACTIVO = 1 ");
 		sb.append("  	AND TPS.ACTIVO = 1 ");
 		sb.append("  	AND ROL.ACTIVO = 1 ");
 		sb.append("  	AND ORI.ACTIVO = 1 ");
 		sb.append("  	AND DES.ACTIVO = 1 ");
 		sb.append("  	AND TPS.TIPOSERVICIO_ID = 2 ");
 		sb.append(" 	AND COR.INDSTATUSCORRIDA = 'H' ");
 		sb.append("  ORDER BY ");
 		sb.append("  	COR.FECHORSALIDA, ");
 		sb.append("  	COR.CORRIDA_ID)");

		Query query = getSession().createSQLQuery(sb.toString()).setResultTransformer(new ResultTransformer() {
			private static final long serialVersionUID = -1157217114834593023L;

			private final int CORRIDAID = 0;
			private final int NUMCORRIDA = 1;
			private final int DESCSERVICO = 2;
			private final int FECHORSALIDA = 3;
			private final int TIPOSERVICIOID = 4;
			private final int DESCSERVICIO = 5;
			private final int ROLOPERATIVOID = 6;
			private final int DESCROLOPERATIVO = 7;
			private final int RUTA_ID = 8;
			private final int ORIGEMID = 9;
			private final int DESCORIGEM = 10;
			private final int DESTINOID = 11;
			private final int DESCDESTINO = 12;
			private final int ORICVEESTADO = 13;
			private final int DESCVEESTADO = 14;
			private final int CLASESERVICIO_ID = 15;
			private final int MARCA_ID = 16;
			private final int FECCORRIDA = 17;
			private final int EMPRESAID = 18;

			@Override
			public List transformList(List list) {
				return list;
			}

			@Override
			public Object transformTuple(Object[] tuple, String[] aliases) {
				CorridaVO corrida = new CorridaVO();

				corrida.setCorridaId(Integer.valueOf(tuple[CORRIDAID] == null ? null : tuple[CORRIDAID].toString()));
				corrida.setNumCorrida(tuple[NUMCORRIDA] == null ? null : Integer.valueOf(tuple[NUMCORRIDA].toString()));
				corrida.setDescServico(tuple[DESCSERVICO] == null ? null : tuple[DESCSERVICO].toString());
				corrida.setFechorsalida(tuple[FECHORSALIDA] == null ? null : tuple[FECHORSALIDA].toString());
				corrida.setTipoServicioVO(new TipoServicioVO(tuple[TIPOSERVICIOID] == null ? null : Integer.valueOf(tuple[TIPOSERVICIOID].toString()), tuple[DESCSERVICIO] == null ? null : tuple[DESCSERVICIO].toString()));
				corrida.setRolOperativoVO(new RolOperativoVO(tuple[ROLOPERATIVOID] == null ? null : Integer.valueOf(tuple[ROLOPERATIVOID].toString()), tuple[DESCROLOPERATIVO] == null ? null : tuple[DESCROLOPERATIVO].toString()));
				corrida.setRutaId(tuple[RUTA_ID] == null ? null : Integer.valueOf(tuple[RUTA_ID].toString()));
				corrida.setOrigenId(tuple[ORIGEMID] == null ? null : Integer.valueOf(tuple[ORIGEMID].toString()));
				corrida.setDescOrigen(tuple[DESCORIGEM] == null ? null : tuple[DESCORIGEM].toString());
				corrida.setDestinoId(tuple[DESTINOID] == null ? null : Integer.valueOf(tuple[DESTINOID].toString()));
				corrida.setDescDestino(tuple[DESCDESTINO] == null ? null : tuple[DESCDESTINO].toString());
				corrida.setOricveestado(tuple[ORICVEESTADO] == null ? null : tuple[ORICVEESTADO].toString());
				corrida.setDescveestado(tuple[DESCVEESTADO] == null ? null : tuple[DESCVEESTADO].toString());
				corrida.setClaseServicioId(tuple[CLASESERVICIO_ID] == null ? null : Integer.valueOf(tuple[CLASESERVICIO_ID].toString()));
				corrida.setMarcaId(tuple[MARCA_ID] == null ? null : Integer.valueOf(tuple[MARCA_ID].toString()));
				corrida.setFeccorrida(tuple[FECCORRIDA] == null ? null : tuple[FECCORRIDA].toString());
				corrida.setEmpresaId(Integer.valueOf(tuple[EMPRESAID] == null ? null : tuple[EMPRESAID].toString()));
				corrida.setLsTramoVO(new ArrayList<TramoVO>());
				corrida.setLsSecuenciaVO(new ArrayList<SecuenciaVO>());

				return corrida;
			}
		});

		query.setInteger("usuarioId", operador);
		query.setInteger("empresaId", empresa.getEmpresaId());
		query.setDate("dtIni", new java.sql.Date(dtIni.getTime()));
		query.setDate("dtFim", new java.sql.Date(dtFim.getTime()));

		return query.list();
	}

	private List getCorridasResumido(Integer operador, Empresa empresa, Date dtIni, Date dtFim, Boolean retornaTramos) throws Exception {
		StringBuilder sb = new StringBuilder();
		start = System.currentTimeMillis();
		
		sb.append("select * from (SELECT");
		sb.append(" 	cor.corrida_id ||';'|| to_char(cor.feccorrida, 'ddMMYYYY') AS chaveCorrida, cor.ruta_id AS rutaId ");		
		sb.append(" FROM OPERADOR_EMBARCADA OPE ");
		sb.append(" JOIN OPERADOR_EMBARCADA_SERVICO OPS ON OPE.OPERADOR_EMBARCADA_ID = OPS.OPERADOR_EMBARCADA_ID AND OPS.ACTIVO = 1 ");
		sb.append(" JOIN ESQUEMA_CORRIDA ESQ ON ESQ.ESQUEMACORRIDA_ID = OPS.ESQUEMA_CORRIDA_ID AND ESQ.ACTIVO = 1 ");
		sb.append(" JOIN CORRIDA COR ON COR.ESQUEMACORRIDA_ID = ESQ.ESQUEMACORRIDA_ID AND COR.ACTIVO = 1 AND COR.INDSTATUSCORRIDA = 'H' ");
		sb.append(" WHERE  OPE.USUARIO_ID = :usuarioId ");
		sb.append(" 	AND COR.EMPRESACORRIDA_ID = :empresaId ");
		sb.append(" 	AND COR.FECCORRIDA >= :dtIni ");
		sb.append(" 	AND COR.FECCORRIDA <= :dtFim ");
		sb.append(" 	AND OPE.ACTIVO = 1 ");
		sb.append(" ORDER BY ");
		sb.append(" 	COR.FECHORSALIDA, ");
		sb.append(" 	COR.CORRIDA_ID) ");
		sb.append(" UNION select * from (SELECT ");
		sb.append("  	cor.corrida_id ||';'|| to_char(cor.feccorrida, 'ddMMYYYY') AS chaveCorrida, cor.ruta_id AS rutaId ");
 		sb.append(" FROM OPERADOR_EMBARCADA OPE ");
 		sb.append(" JOIN OPERADOR_EMBARCADA_LINHA OPL ON OPE.OPERADOR_EMBARCADA_ID = OPL.OPERADOR_EMBARCADA_ID AND OPL.ACTIVO = 1 ");
 		sb.append("  left join operador_embarcada_servico ops on ops.operador_embarcada_id = ope.operador_embarcada_id AND ops.operador_embarcada_servico_id is null ");
 		sb.append("  JOIN CORRIDA COR ON COR.ruta_ID = OPL.ruta_ID AND COR.ACTIVO = 1 AND COR.INDSTATUSCORRIDA = 'H' ");
 		sb.append("  LEFT JOIN ESQUEMA_CORRIDA ESQ ON ESQ.ESQUEMACORRIDA_ID = COR.ESQUEMACORRIDA_ID ");
 		sb.append(" WHERE  OPE.USUARIO_ID = :usuarioId ");
		sb.append(" 	AND COR.EMPRESACORRIDA_ID = :empresaId ");
		sb.append(" 	AND COR.FECCORRIDA >= :dtIni ");
		sb.append(" 	AND COR.FECCORRIDA <= :dtFim ");
		sb.append(" 	AND cor.tiposervicio_id = 2 ");
 		sb.append("  	AND OPE.ACTIVO = 1 ");
 		sb.append("  ORDER BY ");
 		sb.append("  	COR.FECHORSALIDA, ");
 		sb.append("  	COR.CORRIDA_ID)");

		Query query = getSession().createSQLQuery(sb.toString())
				.addScalar("chaveCorrida", StringType.INSTANCE)
				.addScalar("rutaId", IntegerType.INSTANCE);

		query.setInteger("usuarioId", operador);
		query.setInteger("empresaId", empresa.getEmpresaId());
		query.setDate("dtIni", new java.sql.Date(dtIni.getTime()));
		query.setDate("dtFim", new java.sql.Date(dtFim.getTime()));

		List<Object[]> list = query.list();
		if( retornaTramos ) {
			List<CorridaVO> corridas = new ArrayList<CorridaVO>(); 
			for (Object[] chave : list) {
				CorridaVO co = new CorridaVO();
				co.setChaveCorrida((String)chave[0]);
				co.setRutaId((Integer)chave[1] );

				co.setListTramos( obterListaTramo((String)chave[0], (Integer)chave[1]) );
				corridas.add(co);
			}
			
			log.debug( printInfo("getCorridasResumido", start));
			return corridas;
		}else {
			List<String> corridasString = new ArrayList<String>(); 
			for (Object[] chave : list) {
				corridasString.add( (String)chave[0] );
			}
			
			log.debug( printInfo("getCorridasResumido", start));
			return corridasString;
		}
	}
	
	private List<Integer> obterListaTramo( String chave, Integer rutaId ) throws Exception{
		start = System.currentTimeMillis();
		StringBuilder sb = new StringBuilder();

		sb.append(" SELECT");
		sb.append("   TRM.TRAMO_ID ");
		sb.append(" FROM RUTA_COMBINACION RC ");
		sb.append(" JOIN TRAMO TRM ON TRM.TRAMO_ID = RC.TRAMO_ID AND TRM.activo = 1 ");
		sb.append(" JOIN CORRIDA_TRAMO CT ON CT.CORRIDA_ID = :corridaId ");
		sb.append("    AND CT.FECCORRIDA = TO_DATE(:feccorrida, 'DDmmYYYY') ");
		sb.append("    AND CT.DESTINO_ID = TRM.DESTINO_ID ");
		sb.append("    AND CT.activo = 1 ");
		sb.append(" WHERE RC.RUTA_ID = :rutaId ");
		sb.append("    AND RC.activo = 1 ");
		sb.append(" ORDER BY CT.NUMSECUENCIA ");

		Query query = getSession().createSQLQuery(sb.toString()).addScalar("TRAMO_ID", IntegerType.INSTANCE);

		String[] split = chave.split(";");

		query.setParameter("corridaId", split[0] );
		query.setParameter("feccorrida", split[1] );
		query.setParameter("rutaId", rutaId );
		
		List<Integer> list = query.list();
		log.debug( printInfo("obterListaTramo", start));
		return list;

	}
	
	private void preencherTramosSequencias(final CorridaVO corrida, PuntoVenta puntoVenta, Empresa empresa) {
		boolean isTarifaMinimaHabilitado = Boolean.getBoolean(constanteDAO.buscarPorNomeConstante("isTarifaMinimaHabilitado").getValorconstante());
		CategoriaDescuento categoriaDescuento = categoriaDescuentoDAO.pesquisarPorCategoriaEmpresa(Constantes.CATEGORIA_NORMAL, corrida.getEmpresaId());
		
		StringBuilder sb = new StringBuilder();

		sb.append(" SELECT");
		sb.append("     TRM.TRAMO_ID           	AS tramoId, ");
		sb.append("     TRM.DESCTRAMO          	AS desctramo, ");
		sb.append("     TRM.ORIGEN_ID          	AS origemId,");
		sb.append("     ORI.DESCPARADA			AS descOrigem,");
		sb.append("     ORICID.CIUDAD_ID       AS cidadeOrigemId,");
		sb.append("     ORICID.NOMBCIUDAD      AS nomeCidadeOrigem,");
		sb.append("     ORIEST.ESTADO_ID       AS estadoOrigemId,");
		sb.append("     ORIEST.NOMBESTADO      AS nomeEstadoOrigem,");
		sb.append(" 	ORIEST.CVEESTADO       AS cveEstadoOrigem,");
		sb.append(" 	TRM.DESTINO_ID         AS destinoId,");
		sb.append(" 	DES.DESCPARADA         AS descDestino,");
		sb.append(" 	DESCID.CIUDAD_ID       AS cidadeDestinoId,");
		sb.append(" 	DESCID.NOMBCIUDAD      AS nomeCidadeDestino,");
		sb.append(" 	DESEST.ESTADO_ID       AS estadoDestinoId,");
		sb.append(" 	DESEST.NOMBESTADO      AS nomeEstadoDestino,");
		sb.append(" 	DESEST.CVEESTADO       AS cveEstadoDestino,");
		sb.append(" 	TRM.VIA_ID             AS viaId,");
		sb.append(" 	VIA.NOMBVIA            AS nomeVia,");
		sb.append(" 	CRT.NUMSECUENCIA       AS sequencia,");
		sb.append(" 	TA.IMPORTETAXAEMBARQUE AS importeTaxaEmbarque,");
		sb.append(" 	TA.IMPORTEPEDAGIO      AS importePedagio,");
		sb.append(" 	TA.IMPORTEOUTROS       AS importeOutros,");
		sb.append(" 	TA.IMPORTESEGURO       AS importeSeguro,");
		sb.append(" 	TA.PRECIO              AS precio,");
		sb.append(" 	TA.RUTA_ID             as rutaId, ");
		
		/*
		 * não aplica tarifa minina quando configurado no tipo de passagem ou quando nao tem a constante
		 * Mantis #10704 & #20931
		 */
		if(isTarifaMinimaHabilitado && categoriaDescuento !=null && !categoriaDescuento.getIndnaoaplicatarifaminima()) {
			sb.append(" 	(");
			sb.append(" 		select IMPORTETARIFA");
			sb.append(" 		from (");
			sb.append(" 			select");
			sb.append(" 				tmx.TARIFAMINIMA_ID as TARIFAMINIMA_ID,");
			sb.append(" 				tmx.ACTIVO as ACTIVO,");
			sb.append(" 				tmx.CLASESERVICIO_ID as CLASESERVICIO_ID,");
			sb.append(" 				tmx.COEFICIENTETARIFA_ID as COEFICIENTETARIFA_ID,");
			sb.append(" 				tmx.DESTINO_ID as DESTINO_ID,");
			sb.append(" 				tmx.FECMODIF as FECMODIF,");
			sb.append(" 				tmx.IMPORTETARIFA as IMPORTETARIFA,");
			sb.append(" 				tmx.MARCA_ID as MARCA_ID,");
			sb.append(" 				tmx.MONEDA_ID as MONEDA_ID,");
			sb.append(" 				tmx.ORGAOCONCEDENTE_ID as ORGAOCONCEDENTE_ID,");
			sb.append(" 				tmx.ORIGEN_ID as ORIGEN_ID,");
			sb.append(" 				tmx.PLAZA_ID as PLAZA_ID,");
			sb.append(" 				tmx.REGIONMETROPOLITANA_ID as REGIONMETROPOLITANA_ID,");
			sb.append(" 				tmx.RUTA_ID as RUTA_ID,");
			sb.append(" 				tmx.USUARIO_ID as USUARIO_ID,");
			sb.append(" 				tmx.VIGENCIATARIFA_ID as VIGENCIATARIFA_ID,");
			sb.append(" 				ocx.ORGAOCONCEDENTE_ID as orgaoConcedenteId,");
			sb.append(" 				paradaOrigem.PARADA_ID as paradaOrigemId,");
			sb.append(" 				paradaDestino.PARADA_ID as paradaDestinoId,");
			sb.append(" 				ruta.ruta_id as rutaId");
			sb.append(" 			from TARIFA_MINIMA tmx");
			sb.append(" 			join marca m on m.marca_id = tmx.marca_id ");
			sb.append(" 			join empresa e on e.empresa_id = m.empresa_id ");
			sb.append(" 			join PARADA paradaOrigem on paradaOrigem.activo = 1");
			sb.append(" 			join PARADA paradaDestino on paradaDestino.activo = 1");
			sb.append(" 			join RUTA ruta on ruta.activo = 1");
			sb.append(" 			left outer join ORGAO_CONCEDENTE ocx on tmx.ORGAOCONCEDENTE_ID=ocx.ORGAOCONCEDENTE_ID ");
			sb.append(" 			left outer join TARIFA_MINIMA_CATEGORIA tmcx  on tmx.TARIFAMINIMA_ID=tmcx.TARIFAMINIMA_ID and tmcx.ACTIVO = 1 ");
			sb.append(" 			left outer join VIGENCIA_TARIFA vtx on tmx.VIGENCIATARIFA_ID=vtx.VIGENCIATARIFA_ID ");
			sb.append(" 			left outer join REGION_METROPOLITANA rmx on tmx.REGIONMETROPOLITANA_ID=rmx.REGIONMETROPOLITANA_ID ");
			sb.append(" 			left outer join PARADA prmox on rmx.REGIONMETROPOLITANA_ID=prmox.REGIONMETROPOLITANA_ID ");
			sb.append(" 			left outer join PARADA prmdx on rmx.REGIONMETROPOLITANA_ID=prmdx.REGIONMETROPOLITANA_ID ");
			sb.append(" 			where tmx.ACTIVO=1 ");
			sb.append(" 				and (prmox.PARADA_ID in (paradaOrigem.PARADA_ID, -1) or prmox.PARADA_ID is null) ");
			sb.append(" 				and (prmdx.PARADA_ID in (paradaDestino.PARADA_ID, -1) or prmdx.PARADA_ID is null) ");
			sb.append(" 				and (tmx.ORIGEN_ID in (paradaOrigem.PARADA_ID, -1) or tmx.ORIGEN_ID is null) ");
			sb.append(" 				and (tmx.DESTINO_ID in (paradaDestino.PARADA_ID, -1) or tmx.DESTINO_ID is null) ");
			sb.append(" 				and (tmx.PLAZA_ID in (:plazaId, -1)) ");
			sb.append(" 				and (tmx.CLASESERVICIO_ID in (:claseservicioId, -1)) ");
			sb.append(" 				and (e.EMPRESA_ID in (:empresaId, -1)) ");
			sb.append(" 				and (tmcx.TARIFAMINIMACATEGORIA_ID is null or tmcx.CATEGORIA_ID in (:categoriaId, -1)) ");
			sb.append(" 				and tmx.MONEDA_ID=:moneda");
			sb.append(" 				and (ocx.ORGAOCONCEDENTE_ID is null or ocx.ORGAOCONCEDENTE_ID=-1 or ocx.ORGAOCONCEDENTE_ID=(");
			sb.append(" 					select distinct rx.ORGAOCONCEDENTE_ID");
			sb.append(" 					from RUTA rx ");
			sb.append(" 					left outer join RUTA_COMBINACION rcx on rx.RUTA_ID=rcx.RUTA_ID ");
			sb.append(" 					left outer join TRAMO tx on rcx.TRAMO_ID=tx.TRAMO_ID ");
			sb.append(" 					left outer join ORGAO_TRAMO otx on tx.TRAMO_ID=otx.TRAMO_ID ");
			sb.append(" 					where");
			sb.append(" 						rcx.RUTA_ID=ruta.RUTA_ID");
			sb.append(" 						and (");
			sb.append(" 							(tmx.COEFICIENTETARIFA_ID in (otx.COEFICIENTETARIFA1_ID,otx.COEFICIENTETARIFA2_ID,otx.COEFICIENTETARIFA3_ID))");
			sb.append(" 							and tx.ORIGEN_ID=paradaOrigem.parada_id ");
			sb.append(" 							and tx.DESTINO_ID=paradaDestino.parada_id");
			sb.append(" 							or tmx.COEFICIENTETARIFA_ID is null");
			sb.append(" 						)");
			sb.append(" 					)");
			sb.append(" 				)");
			sb.append(" 				and (SYSDATE between vtx.FECINICIOVIGENCIA and vtx.FECFINVIGENCIA)");
			sb.append(" 			order by");
			sb.append(" 				tmx.PLAZA_ID desc,");
			sb.append(" 				tmx.ORIGEN_ID desc,");
			sb.append(" 				tmx.DESTINO_ID desc,");
			sb.append(" 				tmx.CLASESERVICIO_ID desc,");
			sb.append(" 				tmx.MARCA_ID desc");
			sb.append(" 		)");
			sb.append(" 		where");
			sb.append(" 			paradaOrigemId = TRM.ORIGEN_ID");
			sb.append(" 			and paradaDestinoId = TRM.DESTINO_ID");
			sb.append(" 			and rutaId = TA.RUTA_ID");
			sb.append(" 			and rownum = 1");
			sb.append(" 	) as tarifaMinima ");
		}else {
			sb.append(" 	0 as tarifaMinima ");
		}
	
		sb.append(" FROM RUTA_COMBINACION RC");
		sb.append(" JOIN TRAMO TRM ON TRM.TRAMO_ID = RC.TRAMO_ID");
		sb.append(" JOIN CORRIDA_TRAMO CRT ON CRT.DESTINO_ID = TRM.DESTINO_ID AND CRT.CORRIDA_ID = :corridaId AND CRT.FECCORRIDA = TO_DATE(:feccorrida,'DD/MM/YYYY HH24:MI:SS')");
		sb.append(" JOIN PARADA ORI ON ORI.PARADA_ID = TRM.ORIGEN_ID");
		sb.append(" JOIN CIUDAD ORICID ON ORICID.CIUDAD_ID = ORI.CIUDAD_ID");
		sb.append(" JOIN ESTADO ORIEST ON ORIEST.ESTADO_ID = ORICID.ESTADO_ID");
		sb.append(" JOIN PARADA DES ON DES.PARADA_ID = TRM.DESTINO_ID");
		sb.append(" JOIN CIUDAD DESCID ON DESCID.CIUDAD_ID = DES.CIUDAD_ID");
		sb.append(" JOIN ESTADO DESEST ON DESEST.ESTADO_ID = DESCID.ESTADO_ID");
		sb.append(" JOIN VIA VIA  ON VIA.VIA_ID = TRM.VIA_ID");
		sb.append(" JOIN empresa emp ON emp.empresa_id = :empresaId ");
		sb.append(" JOIN marca mar on mar.empresa_id = emp.empresa_id ");
		if (empresa.getIndTabelaPrecoEmbarcada() != null && empresa.getIndTabelaPrecoEmbarcada()) {
			sb.append(" JOIN TARIFA_EMBARCADA TA ON TA.MARCA_ID = mar.marca_Id AND TA.TRAMO_ID = TRM.TRAMO_ID AND TA.RUTA_ID = RC.RUTA_ID");
		} else {
			sb.append(" JOIN TARIFA TA ON TA.MARCA_ID = mar.marca_Id AND TA.TRAMO_ID = TRM.TRAMO_ID AND TA.RUTA_ID = RC.RUTA_ID");
		}
		sb.append(" JOIN VIGENCIA_TARIFA VT ON VT.VIGENCIATARIFA_ID = TA.VIGENCIATARIFA_ID");
		sb.append(" WHERE ");
		sb.append(" 	RC.ACTIVO = 1");
		sb.append(" 	AND TRM.ACTIVO = 1");
		sb.append(" 	AND CRT.ACTIVO = 1");
		sb.append(" 	AND VIA.ACTIVO = 1");
		sb.append(" 	AND TA.ACTIVO = 1");
		sb.append(" 	AND VT.ACTIVO = 1");
		sb.append(" 	AND mar.ACTIVO = 1");
		sb.append(" 	AND coalesce(RC.INDVENTA,0) = 1");
		sb.append(" 	AND RC.RUTA_ID = :rutaId ");
		sb.append(" 	AND TRM.ORIGEN_ID IN (SELECT X.ORIGEN_ID FROM CORRIDA_TRAMO X WHERE X.CORRIDA_ID = :corridaId AND X.FECCORRIDA = TO_DATE(:feccorrida,'DD/MM/YYYY HH24:MI:SS'))");
		sb.append(" 	AND TRM.DESTINO_ID IN (SELECT X.DESTINO_ID FROM CORRIDA_TRAMO X WHERE X.CORRIDA_ID = :corridaId AND X.FECCORRIDA = TO_DATE(:feccorrida,'DD/MM/YYYY HH24:MI:SS'))");
		sb.append("     AND (SYSDATE BETWEEN VT.FECINICIOVIGENCIA AND VT.FECFINVIGENCIA AND VT.ACTIVO = 1)");

		Query query = getSession().createSQLQuery(sb.toString())
				.addScalar("tramoId", IntegerType.INSTANCE)
				.addScalar("desctramo", StringType.INSTANCE)
				.addScalar("origemId", IntegerType.INSTANCE)
				.addScalar("descOrigem", StringType.INSTANCE)
				.addScalar("cidadeOrigemId", IntegerType.INSTANCE)
				.addScalar("nomeCidadeOrigem", StringType.INSTANCE)
				.addScalar("estadoOrigemId", IntegerType.INSTANCE)
				.addScalar("nomeEstadoOrigem", StringType.INSTANCE)
				.addScalar("cveEstadoOrigem", StringType.INSTANCE)
				.addScalar("destinoId", IntegerType.INSTANCE)
				.addScalar("descDestino", StringType.INSTANCE)
				.addScalar("cidadeDestinoId", IntegerType.INSTANCE)
				.addScalar("nomeCidadeDestino", StringType.INSTANCE)
				.addScalar("estadoDestinoId", IntegerType.INSTANCE)
				.addScalar("nomeEstadoDestino", StringType.INSTANCE)
				.addScalar("cveEstadoDestino", StringType.INSTANCE)
				.addScalar("viaId", IntegerType.INSTANCE)
				.addScalar("nomeVia", StringType.INSTANCE)
				.addScalar("sequencia", IntegerType.INSTANCE)
				.addScalar("importeTaxaEmbarque", BigDecimalType.INSTANCE)
				.addScalar("importePedagio", BigDecimalType.INSTANCE)
				.addScalar("importeOutros", BigDecimalType.INSTANCE)
				.addScalar("importeSeguro", BigDecimalType.INSTANCE)
				.addScalar("precio", BigDecimalType.INSTANCE)
				.addScalar("tarifaMinima", BigDecimalType.INSTANCE)
				.setResultTransformer(Transformers.aliasToBean(TramoSequenciaVO.class));

		query.setParameter("empresaId", corrida.getEmpresaId());
		query.setParameter("rutaId", corrida.getRutaId());
		query.setParameter("corridaId", corrida.getCorridaId());
		query.setParameter("feccorrida", corrida.getFeccorrida() + " 00:00:00");
		
		if(isTarifaMinimaHabilitado && categoriaDescuento !=null && !categoriaDescuento.getIndnaoaplicatarifaminima()) {
			query.setParameter("plazaId", puntoVenta.getColonia().getCiudad().getPlaza().getPlazaId());
			query.setParameter("claseservicioId", corrida.getClaseServicioId());
			query.setParameter("categoriaId", Constantes.CATEGORIA_NORMAL);
			query.setParameter("moneda", puntoVenta.getMoneda().getMonedaId());
		}
		
		List<TramoSequenciaVO> tramosequencia = query.list();
		
		HashSet<TramoVO> setTramo = new HashSet<TramoVO>();
		
		List<AliasServico> aliasLs = aliasServicoService.buscarPorRuta(corrida.getRutaId());
		
		for (TramoSequenciaVO ts : tramosequencia) {
			final ParadaVO origem = new ParadaVO(
					ts.getOrigemId(),
					ts.getDescOrigem(),
					ts.getCidadeOrigemId(),
					ts.getNomeCidadeOrigem(),
					ts.getEstadoOrigemId(),
					ts.getNomeEstadoOrigem(),
					ts.getCveEstadoOrigem());

			final ParadaVO destino = new ParadaVO(
					ts.getDestinoId(),
					ts.getDescDestino(),
					ts.getCidadeDestinoId(),
					ts.getNomeCidadeDestino(),
					ts.getEstadoDestinoId(),
					ts.getNomeEstadoDestino(),
					ts.getCveEstadoDestino());

			ViaVO via = new ViaVO(
					ts.getViaId(),
					ts.getNomeVia());

			BigDecimal tarifaMinima = ts.getTarifaMinima();
			
			TramoVO tramo = new TramoVO(
					ts.getTramoId(),
					ts.getDesctramo(),
					origem,
					destino,
					via,
					ts.getSequencia(),
					ts.getPrecio().compareTo(tarifaMinima) < 0 ? tarifaMinima : ts.getPrecio(),
					ts.getImporteTaxaEmbarque()!=null?ts.getImporteTaxaEmbarque():BigDecimal.ZERO,
					ts.getImporteSeguro()!=null?ts.getImporteSeguro():BigDecimal.ZERO,
					ts.getImportePedagio()!=null?ts.getImportePedagio():BigDecimal.ZERO,
					ts.getImporteOutros()!=null?ts.getImporteOutros():BigDecimal.ZERO);
			
			AliasServico aC = null;
			try {
				aC = (AliasServico) CollectionUtils.find(aliasLs, new Predicate() {
					
					@Override
					public boolean evaluate(Object arg0) {
						AliasServico alias = (AliasServico)arg0;
						
						return alias.getCorridaId() != null && alias.getCorridaId().equals(corrida.getCorridaId())
								&& alias.getOrigen().getParadaId().equals(origem.getParadaId())
								&& alias.getDestino().getParadaId().equals(destino.getParadaId());
					}
				});
				
				if(aC == null) {
					aC = (AliasServico) CollectionUtils.find(aliasLs, new Predicate() {
						
						@Override
						public boolean evaluate(Object arg0) {
							AliasServico alias = (AliasServico)arg0;
							
							return alias.getOrigen().getParadaId().equals(origem.getParadaId())
									&& alias.getDestino().getParadaId().equals(destino.getParadaId())
									&& alias.getCorridaId() == null;
						}
					});
				}
			}catch(Throwable th) {
				log.error("erro ao carrgar o alias",th);
			}
			
			if (aC != null) {
				tramo.setAliasdestinoId(aC.getAliasDestino().getParadaId());
				tramo.setAliasorigenId(aC.getAliasOrigen().getParadaId());
				tramo.setDescAliasdestino(aC.getAliasDestino().getDescparada());
				tramo.setDescAliasorigen(aC.getAliasOrigen().getDescparada());
			}
			setTramo.add(tramo);
		}
		
		List<TramoVO> lsTramo = new ArrayList<TramoVO>(setTramo);
		corrida.setLsTramoVO(lsTramo);
	}
	
	public BigDecimal obtenerTarifaMinima(Integer claseServicioId, Integer marcaId, Integer origenConsultaId,
			Integer destinoConsultaId, PuntoVenta miPuntoVenta, Integer rutaId, Integer categoriaId, Boolean indnaoaplicatarifaminima) {
		BigDecimal tarifaMinima = BigDecimal.ZERO;
		
		/*
		 * não aplica tarifa minina quando configurado no tipo de passagem
		 * Mantis #10704
		 */
		if(indnaoaplicatarifaminima != null && indnaoaplicatarifaminima) {
			return tarifaMinima;
		}

		//PuntoVenta miPuntoVenta = PuntoVentaDao.getInstance().findById(puntoVentaId);

		StringBuilder hql = new StringBuilder("select tm from TarifaMinima tm ")
				.append("left join tm.orgaoConcedente oc ")
				.append("left join tm.tarifaMinimaCategorias tmc ")
				.append("left join tm.vigenciaTarifa vige ")
				.append("left join tm.regionMetropolitana.paradaList ori ")
				.append("left join tm.regionMetropolitana.paradaList des ")
				.append("where tm.activo = 1 ").append("and tm.plaza.plazaId in (:plazaId, -1) ")
				.append("and tm.claseServicio.claseservicioId in (:claseServId, -1) ")
				.append("and tm.marca.marcaId in (:marcaId, -1) ")
				.append("and (ori.paradaId in (:origenId, -1) or ori.paradaId is null  )  ")
				.append("and (des.paradaId in (:destinoId,-1) or des.paradaId is null  )  ")
				.append("and (tm.origem.paradaId in (:origenId, -1) or tm.origem.paradaId is null) ")
				.append("and (tm.destino.paradaId in (:destinoId, -1) or tm.destino.paradaId is null) ");

		if (categoriaId != null) {
			hql.append("and (tmc is null or tmc.categoria.categoriaId in (:categoriaId, -1)) ");
		}
		
		hql.append("and tm.moneda.monedaId = :monedaId ")
				.append("and (oc is null or oc.orgaoConcedenteId = -1 or oc.orgaoConcedenteId = ")
				.append("(select distinct r.orgaoConcedente.orgaoConcedenteId from Ruta r")
				.append(" left join r.rutaCombinacionList rc")
				.append(" left join rc.tramo tr")
				.append(" left join tr.lsOrgaoTramo ot")
				.append("	where rc.ruta.rutaId = :rutaId")
				.append(" and (tm.coeficienteTarifa.coeficienteId in ")
				.append(" (ot.coeficienteTarifa1.coeficienteId, ot.coeficienteTarifa2.coeficienteId, ot.coeficienteTarifa3.coeficienteId ) ")
				.append(" and tr.origem.paradaId = :origenId ")
				.append(" and tr.destino.paradaId = :destinoId ")
				.append(" or tm.coeficienteTarifa is null )  )) ")
				.append(" and " + DBUtil.getInstance().dbSysdate() + " between vige.feciniciovigencia and vige.fecfinvigencia ")
		
				.append("order by tm.plaza.plazaId desc, tm.origem.paradaId desc, ")
				.append("tm.destino.paradaId desc, tm.claseServicio.claseservicioId desc, ")
				.append("tm.marca.marcaId desc");

		Query miQry = getSession().createQuery(hql.toString());
		miQry.setInteger("plazaId", miPuntoVenta.getColonia().getCiudad().getPlaza().getPlazaId());
		miQry.setInteger("claseServId", claseServicioId);
		miQry.setInteger("marcaId", marcaId);
		miQry.setInteger("origenId", origenConsultaId);
		miQry.setInteger("destinoId", destinoConsultaId);
		miQry.setInteger("monedaId", miPuntoVenta.getMoneda().getMonedaId());
		miQry.setInteger("rutaId", rutaId);

		if (categoriaId != null) {
			miQry.setInteger("categoriaId", categoriaId);
		}

		List<TarifaMinima> listTarifaMinima = miQry.list();
		if (!listTarifaMinima.isEmpty()) {
			tarifaMinima = listTarifaMinima.get(0).getImportetarifa();
		}

		return tarifaMinima;
	}

	private void preencherSequencias(CorridaVO corrida) {
		final int NUMSECUENCIA = 0;
		final int ORIGEN_ID = 1;
		final int ORIGENCVEPARADA = 2;
		final int ORIGENDESCPARADA = 3;
		final int ORIGENCIUDAD_ID = 4;
		final int ORIGENNOMBCIUDAD = 5;
		final int ORIGENESTADO_ID = 6;
		final int ORIGENNOMBESTADO = 7;
		final int ORIGENCVEESTADO = 8;
		final int DESTINO_ID = 9;
		final int DESTINOCVEPARADA = 10;
		final int DESTINODESCPARADA = 11;
		final int DESTINOCIUDAD_ID = 12;
		final int DESTINONOMBCIUDAD = 13;
		final int DESTINOESTADO_ID = 14;
		final int DESTINONOMBESTADO = 15;
		final int DESTINOCVEESTADO = 16;

		StringBuilder sb = new StringBuilder();

		sb.append(" SELECT");
		sb.append("   CT.NUMSECUENCIA,");
		sb.append("   CT.ORIGEN_ID , PO.CVEPARADA as PO_CVEPARADA, PO.DESCPARADA as PO_DESCPARADA, CO.CIUDAD_ID as CO_CIUDAD_ID, CO.NOMBCIUDAD as CO_NOMBCIUDAD, EO.ESTADO_ID as EO_ESTADO_ID, EO.NOMBESTADO as EO_NOMBESTADO, EO.CVEESTADO as EO_CVEESTADO,");
		sb.append("   CT.DESTINO_ID, PD.CVEPARADA as PD_CVEPARADA, PD.DESCPARADA as PD_DESCPARADA, CD.CIUDAD_ID as CD_CIUDAD_ID, CD.NOMBCIUDAD as CD_NOMBCIUDAD, ED.ESTADO_ID as ED_ESTADO_ID, ED.NOMBESTADO as ED_NOMBESTADO, ED.CVEESTADO as ED_CVEESTADO");
		sb.append(" FROM CORRIDA C");
		sb.append(" JOIN CORRIDA_TRAMO CT ON CT.CORRIDA_ID = C.CORRIDA_ID AND CT.FECCORRIDA = C.FECCORRIDA");
		sb.append(" JOIN PARADA PO ON PO.PARADA_ID = CT.ORIGEN_ID");
		sb.append(" JOIN CIUDAD CO ON CO.CIUDAD_ID = PO.CIUDAD_ID");
		sb.append(" JOIN ESTADO EO ON EO.ESTADO_ID = CO.ESTADO_ID");
		sb.append(" JOIN PARADA PD ON PD.PARADA_ID = CT.DESTINO_ID");
		sb.append(" JOIN CIUDAD CD ON CD.CIUDAD_ID = PD.CIUDAD_ID");
		sb.append(" JOIN ESTADO ED ON ED.ESTADO_ID = CD.ESTADO_ID");
		sb.append(" WHERE C.CORRIDA_ID = :corridaId AND C.FECCORRIDA = TO_DATE(:feccorrida,'DD/MM/YYYY HH24:MI:SS') and CT.activo = 1 ");
		sb.append(" ORDER BY CT.NUMSECUENCIA");

		Query query = getSession().createSQLQuery(sb.toString());

		query.setParameter("corridaId", corrida.getCorridaId());
		query.setParameter("feccorrida", corrida.getFeccorrida() + " 00:00:00");

		List<SecuenciaVO> lsSecuenciaVO = new ArrayList<SecuenciaVO>();
		List<String> controle = new ArrayList<String>(0);

		List<Object[]> list = query.list();

		for (Object[] item : list) {
			final Integer origensecuencia = Integer.valueOf(item[NUMSECUENCIA].toString());
			final Integer origen_id = Integer.valueOf(item[ORIGEN_ID].toString());
			item[ORIGENCVEPARADA].toString();
			final String origendescparada = item[ORIGENDESCPARADA].toString();
			final Integer origenciudad_id = Integer.valueOf(item[ORIGENCIUDAD_ID].toString());
			final String origennombciudad = item[ORIGENNOMBCIUDAD].toString();
			final Integer origenestado_id = Integer.valueOf(item[ORIGENESTADO_ID].toString());
			final String origennombestado = item[ORIGENNOMBESTADO].toString();
			final String origencveestado = item[ORIGENCVEESTADO].toString();

			final Integer destinosecuencia = Integer.valueOf(item[NUMSECUENCIA].toString()) + 1;
			final Integer destino_id = Integer.valueOf(item[DESTINO_ID].toString());
			item[DESTINOCVEPARADA].toString();
			final String destinodescparada = item[DESTINODESCPARADA].toString();
			final Integer destinociudad_id = Integer.valueOf(item[DESTINOCIUDAD_ID].toString());
			final String destinonombciudad = item[DESTINONOMBCIUDAD].toString();
			final Integer destinoestado_id = Integer.valueOf(item[DESTINOESTADO_ID].toString());
			final String destinonombestado = item[DESTINONOMBESTADO].toString();
			final String destinocveestado = item[DESTINOCVEESTADO].toString();

			adicionarSequencia(
					controle,
					lsSecuenciaVO,
					origensecuencia,
					origen_id,
					origendescparada,
					origenciudad_id,
					origennombciudad,
					origenestado_id,
					origennombestado,
					origencveestado);

			adicionarSequencia(
					controle,
					lsSecuenciaVO,
					destinosecuencia,
					destino_id,
					destinodescparada,
					destinociudad_id,
					destinonombciudad,
					destinoestado_id,
					destinonombestado,
					destinocveestado);
		}

		corrida.setLsSecuenciaVO(lsSecuenciaVO);
	}

	private void adicionarSequencia(List<String> controle, List<SecuenciaVO> lsSecuenciaVO, final Integer numsecuencia, final Integer paradaId, final String descParada, final Integer ciudadId, final String nombCiudad, final Integer estadoId, final String nombEstado, final String cveEstado) {
		final String key = numsecuencia.toString() + "|" + paradaId.toString();

		if (!controle.contains(key)) {
			SecuenciaVO sequencia = new SecuenciaVO(
					numsecuencia,
					new ParadaVO(paradaId, descParada, ciudadId, nombCiudad, estadoId, nombEstado, cveEstado));

			lsSecuenciaVO.add(sequencia);

			controle.add(key);
		}
	}
}
