package com.rjconsultores.ventaboletos.dao.hibernate;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.hibernate.type.BooleanType;
import org.hibernate.type.LongType;
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 org.zkoss.util.resource.Labels;

import com.rjconsultores.ventaboletos.ArquivoRemessa;
import com.rjconsultores.ventaboletos.ArquivoRemessaItem;
import com.rjconsultores.ventaboletos.ArquivoRemessaItemInteface;
import com.rjconsultores.ventaboletos.blocos.DetalheMulta;
import com.rjconsultores.ventaboletos.blocos.DetalheObrigatorio;
import com.rjconsultores.ventaboletos.blocos.DetalheRetorno;
import com.rjconsultores.ventaboletos.blocos.RodapeRemessaPadrao;
import com.rjconsultores.ventaboletos.blocos.bancobrasil.ArquivoRemessaBancoBrasil;
import com.rjconsultores.ventaboletos.blocos.bancobrasil.CabecalhoLoteRemessaBancoBrasil;
import com.rjconsultores.ventaboletos.blocos.bancobrasil.CabecalhoRemessaBancoBrasil;
import com.rjconsultores.ventaboletos.blocos.bancobrasil.DetalheObrigatorioDadosPagadorBancoBrasil;
import com.rjconsultores.ventaboletos.blocos.bancobrasil.DetalheObrigatorioDadosTitulosBancoBrasil;
import com.rjconsultores.ventaboletos.blocos.bancobrasil.RodapeRemessaBancoBrasil;
import com.rjconsultores.ventaboletos.blocos.bancobrasil.RodapeRemessaLoteBancoBrasil;
import com.rjconsultores.ventaboletos.blocos.bradesco.ArquivoRemessaBradesco;
import com.rjconsultores.ventaboletos.blocos.bradesco.CabecalhoRemessaBradesco;
import com.rjconsultores.ventaboletos.blocos.bradesco.DetalheObrigatorioBradesco;
import com.rjconsultores.ventaboletos.blocos.caixa.ArquivoRemessaCaixa;
import com.rjconsultores.ventaboletos.blocos.caixa.CabecalhoRemessaCaixa;
import com.rjconsultores.ventaboletos.blocos.caixa.DetalheObrigatorioCaixa;
import com.rjconsultores.ventaboletos.blocos.itau.ArquivoRemessaItau;
import com.rjconsultores.ventaboletos.blocos.itau.CabecalhoRemessaItau;
import com.rjconsultores.ventaboletos.blocos.itau.DetalheObrigatorioItau;
import com.rjconsultores.ventaboletos.blocos.mercantil.ArquivoRemessaMercantil;
import com.rjconsultores.ventaboletos.blocos.mercantil.CabecalhoRemessaMercantil;
import com.rjconsultores.ventaboletos.blocos.mercantil.DetalheObrigatorioMercantil;
import com.rjconsultores.ventaboletos.blocos.safra.ArquivoRemessaSafra;
import com.rjconsultores.ventaboletos.blocos.safra.CabecalhoRemessaSafra;
import com.rjconsultores.ventaboletos.blocos.safra.DetalheObrigatorioSafra;
import com.rjconsultores.ventaboletos.blocos.safra.RodapeRemessaSafra;
import com.rjconsultores.ventaboletos.blocos.santander.ArquivoRemessaSantander;
import com.rjconsultores.ventaboletos.blocos.santander.CabecalhoRemessaSantander;
import com.rjconsultores.ventaboletos.blocos.santander.DetalheObrigatorioSantander;
import com.rjconsultores.ventaboletos.blocos.sicoob.ArquivoRemessaSicoob;
import com.rjconsultores.ventaboletos.blocos.sicoob.CabecalhoLoteRemessaSicoob;
import com.rjconsultores.ventaboletos.blocos.sicoob.CabecalhoRemessaSicoob;
import com.rjconsultores.ventaboletos.blocos.sicoob.DetalheObrigatorioDadosPagadorSicoob;
import com.rjconsultores.ventaboletos.blocos.sicoob.DetalheObrigatorioSicoob;
import com.rjconsultores.ventaboletos.blocos.sicoob.RodapeRemessaLoteSicoob;
import com.rjconsultores.ventaboletos.blocos.sicoob.RodapeRemessaSicoob;
import com.rjconsultores.ventaboletos.dao.RemessaCNABBancosDAO;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.FechamentoBoleto;
import com.rjconsultores.ventaboletos.entidad.FechamentoCntcorrente;
import com.rjconsultores.ventaboletos.entidad.PuntoVenta;
import com.rjconsultores.ventaboletos.enuns.Aceite;
import com.rjconsultores.ventaboletos.enuns.BancoLayout;
import com.rjconsultores.ventaboletos.enuns.TipoInscricaoPagador;
import com.rjconsultores.ventaboletos.exception.ComissaoException;
import com.rjconsultores.ventaboletos.exception.ValidacaoRemessaException;
import com.rjconsultores.ventaboletos.utilerias.ApplicationProperties;
import com.rjconsultores.ventaboletos.utilerias.CustomEnum;
import com.rjconsultores.ventaboletos.utilerias.DateUtil;

@Repository("remessaCNABBancosDAO")
@SuppressWarnings({"unchecked"})
public class RemessaCNABBancosHibernateDAO extends GenericHibernateDAO<FechamentoBoleto, Long> implements RemessaCNABBancosDAO{
	
	private static final String NUMERAIS = "[^0-9]+";
	private static final String DATA_ATE = "dataAte";
	private static final String DATA_DE = "dataDe";
	private static final String EMPRESA_ID = "empresaId";
	private static final String ZERO_ESQUERDA = "00000000";
	private static final Logger log = LogManager.getLogger(RemessaCNABBancosHibernateDAO.class);
	
	@Autowired
    public RemessaCNABBancosHibernateDAO(@Qualifier("sessionFactory") SessionFactory factory) {
        setSessionFactory(factory);
    }
	
	public String findBanco(Empresa empresa){
		
		StringBuilder sb = new StringBuilder();
		sb.append("SELECT DISTINCT fp.BOLETO_BANCO_COD ");
		sb.append("FROM ");
		sb.append("FECHAMENTO_PARAMGERAL fp ");
		sb.append("WHERE fp.activo = 1 AND ");
		sb.append("fp.EMPRESA_ID = " + empresa.getEmpresaId());
		
		Query query = getSession().createSQLQuery(sb.toString());
		
		return (String) query.list().get(0);
	}
	
	public ArquivoRemessa remessaBradesco(Empresa empresa, Date dataDe, Date dataAte, Boolean reenviar) throws Exception{
		
		StringBuilder sb = new StringBuilder();
		
		sb.append("SELECT ");
		sb.append("fb.FECHAMENTOBOLETO_ID AS \"id\", ");
		sb.append("(NVL(fp.COUNT_REMESSA, 0) + 1)  AS \"idRemessa\", ");
		sb.append("fp.COD_EMP_BANCO AS \"codEmpresaBanco\", ");
		sb.append("emp.NOMBEMPRESA AS \"nomeEmpresa\", ");
		sb.append("fp.BOLETO_BANCO_AGENCIA AS \"agencia\", ");
		sb.append("fp.BOLETO_BANCO_CONTA AS \"conta\", "); 
		sb.append("fp.BOLETO_BANCO_CONTA_DIGITO AS \"dac\", "); 
		sb.append("fp.BOLETO_BANCO_CARTEIRA AS \"carteira\", ");
		sb.append("fb.NOSSONUMERO AS \"nossoNumero\", ");
		sb.append("fb.FECVENCIMENTO AS \"vencimento\", ");
		sb.append("fb.VALORDOCUMENTO AS \"valor\", ");
		sb.append("'01' AS \"especieTitulo\", ");
		sb.append("fb.FECDOCUMENTO AS \"dataEmissao\", ");
		sb.append("'00' AS \"instrucao1\", ");
		sb.append("'00' AS \"instrucao2\", ");
		sb.append("fb.MORA AS \"valorAtraso\", ");
		sb.append("fb.DESCONTOS AS \"valorDesconto\", ");
		sb.append("fb.DEDUCOES AS \"valorAbatimento\", ");
		sb.append("'cnpj' as \"tipoInscricaoPagador\", ");
		sb.append("pv.NUMDOCPUNTOVENTA AS \"numeroInscricaoPagador\", ");
		sb.append("pv.NOMBPUNTOVENTA AS \"nomePagador\", ");
		sb.append("pv.DIRECCIONCALLE || ', ' || pv.DIRECCIONNUMERO || ', ' ||  pl.NOMBPLAZA || ', ' || ci.NOMBCIUDAD  || ', ' || es.NOMBESTADO AS \"enderecoCompletoPagador\", ");
		sb.append("pv.CODPOSTAL AS \"cepPagador\", ");
		sb.append("nvl(fb.porc_mora, 0) AS \"porcentagemMora\", ");
		sb.append("nvl(fb.porc_multa, 0) AS \"porcentagemMulta\" ");
		
		writeFROMClause(sb, dataDe != null && dataAte != null, reenviar);
		
		Query query = getSession().createSQLQuery(sb.toString());
		query.setInteger(EMPRESA_ID, empresa.getEmpresaId());
		
		if(dataDe != null && dataAte != null){
			query.setDate(DATA_DE, dataDe);
			query.setDate(DATA_ATE, dataAte);
		}
		List<Object[]> list = query.list();
		
		ArquivoRemessa arquivoRemessa = new ArquivoRemessa(BancoLayout.BRADESCO_400_Envio);
		
		String nomeArquivo = "CB" + new SimpleDateFormat("ddMM").format(new Date());
		int variavel = 0;
		
		ArquivoRemessaItem arquivoRemessaItem = null;
		CabecalhoRemessaBradesco cabecalhoRemessaBradesco = null;
		
		boolean constanteValidacao = ApplicationProperties.getInstance().isCustomHabilitado(CustomEnum.IS_VALIDAR_CONSTANTE_REMESSA.getDescricao());
		
		for(Object[] tupla : list){
			
			Integer idRemessa = Integer.valueOf(tupla[1].toString());
			variavel = idRemessa;
			String codEmpresaBanco = tupla[2] != null ? tupla[2].toString() : "0";
			String nomeEmpresa = tupla[3].toString();
			
			if(!tupla[8].toString().contains("-")){
				log.error( String.format( "NossoNumero não está no formato correto: %s1 . Ignorando o registro FechamentoBoletoId = %s2 " , tupla[0].toString()));
				continue;
			}
					
			if(cabecalhoRemessaBradesco == null || !cabecalhoRemessaBradesco.getCodigoEmpresa().equals(codEmpresaBanco) ){
				cabecalhoRemessaBradesco = new CabecalhoRemessaBradesco();
				cabecalhoRemessaBradesco.setNumeroSequencialRemessa(idRemessa);
				cabecalhoRemessaBradesco.setDataGravacao(new Date());
				cabecalhoRemessaBradesco.setCodigoEmpresa(codEmpresaBanco);
				cabecalhoRemessaBradesco.setNomeEmpresa(nomeEmpresa);
				
				arquivoRemessaItem = new ArquivoRemessaBradesco();
				arquivoRemessaItem.setCabecalhoRemessa(cabecalhoRemessaBradesco);
				arquivoRemessaItem.setRodapeRemessa(new RodapeRemessaPadrao());
				
				arquivoRemessa.addItem(arquivoRemessaItem);
			}
			
			DetalheObrigatorioBradesco detalhe = new DetalheObrigatorioBradesco();  
			
			String []doc = tupla[8].toString().split("-");
			
			detalhe.setIdBoletoFechamento(Integer.valueOf(tupla[0].toString()));
			detalhe.setCarteira(tupla[7].toString());
			detalhe.setAgencia(tupla[4].toString());
			detalhe.setContacorrente(tupla[5].toString());
			detalhe.setDvConta(tupla[6].toString());
			detalhe.setNumeroControleDoParticipante(tupla[0].toString());
			detalhe.setNossoNumeroComDigito(doc[0] + doc[1]);
			detalhe.setCodigoDeOcorrencia(0);
			detalhe.setDataOcorrencia(null);
			detalhe.setNumeroDoDocumento(StringUtils.right(doc[0], 10));
			detalhe.setVencimento((Date) tupla[9]);
			detalhe.setValor(new BigDecimal(tupla[10].toString().replace(",", ".")));
			detalhe.setEmissao((Date) tupla[12]);
			detalhe.setPercentualMulta( (BigDecimal) tupla[24] );
			
			if (!constanteValidacao) {
				detalhe.setEspecieDeTitulo("01");
				detalhe.setInstrucao1("00");
				detalhe.setInstrucao2("00");
			}else {
				detalhe.setEspecieDeTitulo(tupla[11].toString());
				detalhe.setInstrucao1(tupla[13].toString());
				detalhe.setInstrucao2(tupla[14].toString());
			}
			
			detalhe.setDataLimiteDesconto(null);
			detalhe.setValorIOF(BigDecimal.ZERO);
			detalhe.setTipoInscricaoPagador(TipoInscricaoPagador.CNPJ);
			detalhe.setNomePagador(tupla[20].toString());
			detalhe.setSacador_Avalista_Mensagem2("");
			detalhe.setMensagem1("");
			
			try{
				if( tupla[15] != null ) {
					detalhe.setValorAtraso(new BigDecimal(tupla[15].toString().replace(",", ".")));
				}else if( tupla[23] != null ) {
					detalhe.setValorAtraso( calculaValorMora( (BigDecimal) tupla[23], new BigDecimal(tupla[10].toString().replaceAll(",", ".") ))  );
				}else {
					detalhe.setValorAtraso( BigDecimal.ZERO );
				}
				
			}catch(Exception e){
				throw new ValidacaoRemessaException("Erro ao setar o valor de atraso do boleto "+tupla[0]+", favor entrar em contato com o suporte! ");
			}
			
			try{
				detalhe.setValorDesconto(new BigDecimal(tupla[16].toString().replace(",", ".")));
			}catch(Exception e){
			}
			
			try{
				detalhe.setValorAbatimentoConcedido(new BigDecimal(tupla[17].toString().replace(",", ".")));
			}catch(Exception e){
			}
			
			try{
				detalhe.setNumeroInscricaoPagador(tupla[19].toString().replaceAll(NUMERAIS, ""));
			}catch(Exception e){
				throw new ValidacaoRemessaException("O CNPJ do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setEnderecoCompletoPagador(tupla[21].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Endereço do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			try{
				String cep = tupla[22].toString();
				detalhe.setCEP_Prefixo(cep.substring(0,5));
				detalhe.setCEP_Sufixo(cep.substring(5));
			}catch(Exception e){
				throw new ValidacaoRemessaException("O CEP do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}			
			
			arquivoRemessaItem.addTitulo(detalhe);
			
			arquivoRemessaItem.getRodapeRemessa().setNumeroSequencialRegistro(arquivoRemessa.getItens().size());
			
		}
		
		nomeArquivo = nomeArquivo + new DecimalFormat("##").format(variavel) + ".REM";
		arquivoRemessa.setNomeArquivo(nomeArquivo);
	
		return arquivoRemessa;
		
	}
	
	public ArquivoRemessa remessaSafra(Empresa empresa, Date dataDe, Date dataAte, Boolean reenviar) throws Exception{
		
		StringBuilder sb = new StringBuilder();
		
		sb.append("SELECT ");
		sb.append("fb.FECHAMENTOBOLETO_ID AS \"id\", ");
		sb.append("(NVL(fp.COUNT_REMESSA, 0) + 1)  AS \"idRemessa\", ");		
		sb.append("emp.NOMBEMPRESA AS \"nomeEmpresa\", ");
		sb.append("emp.CNPJ AS \"cnpj\", ");
		sb.append("fp.BOLETO_BANCO_AGENCIA AS \"agencia\", ");
		sb.append("fp.BOLETO_BANCO_CONTA AS \"conta\", "); 
		sb.append("fp.BOLETO_BANCO_CONTA_DIGITO AS \"dac\", ");		
		sb.append("fb.NOSSONUMERO AS \"nossoNumero\", ");
		sb.append("fb.FECVENCIMENTO AS \"vencimento\", ");
		sb.append("fb.VALORDOCUMENTO AS \"valor\", ");
		sb.append("fb.FECDOCUMENTO AS \"dataEmissao\", ");
		sb.append("'01' AS \"instrucao1\", ");
		sb.append("'01' AS \"instrucao2\", ");
		sb.append("nvl(fb.porc_multa, 0) AS \"porcentagemMulta\", ");
		sb.append("nvl(fb.porc_mora, 0) AS \"porcentagemMora\", ");
		sb.append("fb.MORA AS \"valorAtraso\", ");
		sb.append("fb.DESCONTOS AS \"valorDesconto\", ");
		sb.append("fb.DEDUCOES AS \"valorAbatimento\", ");
		sb.append("pv.NUMDOCPUNTOVENTA AS \"numeroInscricaoPagador\", ");
		sb.append("pv.NOMBPUNTOVENTA AS \"nomePagador\", ");
		sb.append("pv.DIRECCIONCALLE || ', ' || pv.DIRECCIONNUMERO AS \"logradouroPagador\", ");
		sb.append("pl.NOMBPLAZA AS \"bairroPagador\", ");
		sb.append("pv.CODPOSTAL AS \"cepPagador\", ");
		sb.append("ci.NOMBCIUDAD AS \"cidadePagador\", ");
		sb.append("es.CVEESTADO AS \"estadoPagador\" ");
		
		writeFROMClause(sb, dataDe != null && dataAte != null, reenviar);
		
		Query query = getSession().createSQLQuery(sb.toString());
		query.setInteger(EMPRESA_ID, empresa.getEmpresaId());
		
		if(dataDe != null && dataAte != null){
			query.setDate(DATA_DE, dataDe);
			query.setDate(DATA_ATE, dataAte);
		}
		List<Object[]> list = query.list();
		
		ArquivoRemessa arquivoRemessa = new ArquivoRemessa(BancoLayout.SAFRA_400_Envio);
		
		String nomeArquivo = "CB" + new SimpleDateFormat("ddMM").format(new Date());
		
		int variavel = 0;
		int seqRegistro = 0;
		int qtdeTitulos = 0;
		
		BigDecimal valorTitulos = BigDecimal.ZERO;
		ArquivoRemessaItem arquivoRemessaItem = null;
		CabecalhoRemessaSafra cabecalho = null;
		
		for(Object[] tupla : list){
			
			Integer idRemessa = Integer.valueOf(tupla[1].toString());			
			BigDecimal valor = new BigDecimal(tupla[9].toString().replace(",", "."));			
			
			qtdeTitulos++;
			valorTitulos = valorTitulos.add( valor );
			String nomeEmpresa = tupla[2].toString();
			String agencia = tupla[4].toString();
			String conta = tupla[5].toString();
			String digiConta = tupla[6].toString();
			Date vencimento = (Date) tupla[8];
			
			if(!tupla[7].toString().contains("-")){
				log.error(String.format( "NossoNumero não está no formato correto: %s1 . Ignorando o registro FechamentoBoletoId = %s2 " , tupla[7], tupla[0]));
				continue;
			}
					
			if(cabecalho == null ){
				variavel = idRemessa;
				
				cabecalho = new CabecalhoRemessaSafra();				
				cabecalho.setNumAgencia(agencia);
				cabecalho.setNumContaCorrente(conta);
				cabecalho.setDigContaCorrente(digiConta);
				cabecalho.setNomeEmpresa(nomeEmpresa);
				cabecalho.setDataGravacao(new Date());
				cabecalho.setNumeroSequencialRemessa(idRemessa);
				cabecalho.setNumeroSequencialRegistro(++seqRegistro);
				
				arquivoRemessaItem = new ArquivoRemessaSafra();
				arquivoRemessaItem.setCabecalhoRemessa(cabecalho);
				
				arquivoRemessa.addItem(arquivoRemessaItem);
			}
			
			DetalheObrigatorioSafra detalhe = new DetalheObrigatorioSafra();		
			
			detalhe.setCpfCnpj(Integer.parseInt(TipoInscricaoPagador.CNPJ.getId()));
			detalhe.setNumCpfCnpj(tupla[3].toString());
			detalhe.setNumAgencia(agencia);						
			detalhe.setNumContaCorrente(conta);
			detalhe.setDigContaCorrente(digiConta);
			detalhe.setNossoNumero(tupla[7].toString());
			detalhe.setIdBoletoFechamento(Integer.valueOf(tupla[0].toString()));			
			detalhe.setVencimento(vencimento);
			detalhe.setValor(valor);
			detalhe.setAceite(Aceite.ACEITE);
			detalhe.setDataEmissao((Date) tupla[10]);
			detalhe.setInstrucao1(tupla[11].toString());
			detalhe.setInstrucao2(tupla[12].toString());
			try{
				detalhe.setPercMulta( new BigDecimal(tupla[13].toString().replace(",", ".") ) );				
				if( tupla[15] != null ) {
					detalhe.setJurosDeMora(new BigDecimal(tupla[15].toString().replace(",", ".")));
				}else {
					detalhe.setJurosDeMora( calculaValorMora( (BigDecimal) tupla[14], valor ));
				}
				detalhe.setDataMulta(vencimento);
			}catch(NullPointerException e){
				detalhe.setPercMulta(BigDecimal.ZERO);
				detalhe.setDataMulta(vencimento);
				detalhe.setJurosDeMora(BigDecimal.ZERO);
			}
			
			try{				
				detalhe.setDataLimiteDesconto(vencimento);
				detalhe.setValorDesconto(new BigDecimal(tupla[16].toString().replace(",", ".")));
			}catch(NullPointerException e){				
				detalhe.setDataLimiteDesconto(vencimento);
				detalhe.setValorDesconto(BigDecimal.ZERO);
			}
			
			detalhe.setValorIOF(BigDecimal.ZERO);
			
			try{
				detalhe.setValorAbatimentoConcedido(new BigDecimal(tupla[17].toString().replace(",", ".")));
			}catch(NullPointerException e){
				detalhe.setValorAbatimentoConcedido(BigDecimal.ZERO);
			}
			
			detalhe.setTipoInscricaoPagador(TipoInscricaoPagador.CNPJ);		
			
			try{
				detalhe.setNumeroInscricaoPagador(tupla[18].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O CNPJ do ponto de venda "+tupla[18]+" está fora do padrão, favor corrigir");
			}
			
			detalhe.setNomePagador(tupla[19].toString());
			
			try{
				detalhe.setEnderecoPagador(tupla[20].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Logradouro do ponto de venda "+tupla[18]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setBairroPagador(tupla[21].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Bairro do ponto de venda "+tupla[18]+" está fora do padrão, favor corrigir");
			}
			
			detalhe.setCepPagador(tupla[22].toString());
			
			try{
				detalhe.setCidadePagador(tupla[23].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("A cidade do ponto de venda "+tupla[18]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setEstadoPagador(tupla[24].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Estado do ponto de venda "+tupla[18]+" está fora do padrão, favor corrigir");
			}
			
			detalhe.setSacadorAvalista("");			
			detalhe.setNumeroSequencialRemessa(idRemessa);
			detalhe.setNumeroSequencialRegistro(++seqRegistro);
			
			arquivoRemessaItem.addTitulo(detalhe);
			
		}
		
		if(arquivoRemessaItem != null){
				
			RodapeRemessaSafra rodape = new RodapeRemessaSafra();
			rodape.setQtdTitulos(qtdeTitulos);
			rodape.setValorTotalTitulos(valorTitulos);
			
			rodape.setNumeroSequencialRemessa(variavel);
			rodape.setNumeroSequencialRegistro(++seqRegistro);
			
			arquivoRemessaItem.setRodapeRemessa(rodape);
		}

		nomeArquivo = nomeArquivo + new DecimalFormat("##").format(variavel) + ".REM";
		arquivoRemessa.setNomeArquivo(nomeArquivo);
	
		return arquivoRemessa;
		
	}
	
	public ArquivoRemessa remessaSantander(Empresa empresa, Date dataDe, Date dataAte, Boolean reenviar) throws Exception{
		
		StringBuilder sb = new StringBuilder();
		
		sb.append("SELECT ");
		sb.append(" fb.FECHAMENTOBOLETO_ID AS \"id\", "); //0
		sb.append(" (NVL(fp.COUNT_REMESSA, 0) + 1)  AS \"idRemessa\", ");  //1
		sb.append(" fp.COD_EMP_BANCO AS \"codEmpresaBanco\", "); //2
		sb.append(" emp.NOMBEMPRESA AS \"nomeEmpresa\", "); //3
		sb.append(" fp.BOLETO_BANCO_AGENCIA AS \"agencia\", "); //4
		sb.append(" fp.BOLETO_BANCO_CONTA AS \"conta\", ");  //5
		sb.append(" fp.BOLETO_BANCO_CONTA_DIGITO AS \"dac\", "); //6 
		sb.append(" fp.BOLETO_BANCO_CARTEIRA AS \"carteira\", "); //7
		sb.append(" fb.NOSSONUMERO AS \"nossoNumero\", "); //8
		sb.append(" fb.FECVENCIMENTO AS \"vencimento\", "); //9
		sb.append(" fb.VALORDOCUMENTO AS \"valor\", "); //10
		sb.append(" '01' AS \"especieTitulo\", "); //11
		sb.append(" fb.FECDOCUMENTO AS \"dataEmissao\", ");//12
		sb.append(" '00' AS \"instrucao1\", ");//13
		sb.append(" '00' AS \"instrucao2\", ");//14
		sb.append(" fb.MORA AS \"valorAtraso\", ");//15
		sb.append(" fb.DESCONTOS AS \"valorDesconto\", ");//16
		sb.append(" fb.DEDUCOES AS \"valorAbatimento\", ");//17
		sb.append(" 'cnpj' as \"tipoInscricaoPagador\", ");//18
		sb.append(" pv.NUMDOCPUNTOVENTA AS \"numeroInscricaoPagador\", ");//19
		sb.append(" pv.NOMBPUNTOVENTA AS \"nomePagador\", ");//20
		sb.append(" pv.DIRECCIONCALLE || ', ' || pv.DIRECCIONNUMERO as endereco,");//21
		sb.append(" pl.NOMBPLAZA as bairro, ");//22
		sb.append(" ci.NOMBCIUDAD  AS cidade, ");//23
		sb.append(" es.CVEESTADO AS estado, ");//24
		sb.append(" pv.CODPOSTAL AS \"cepPagador\", "); //25
		sb.append(" ecb.NUMINTEGRACION AS \"codigoTransmissao\", "); //26
		sb.append(" fp.BOLETO_BANCO_AGENCIA_DIGITO AS \"agenciaDigito\", "); //27
		sb.append(" emp.CNPJ AS \"numeroInscricaoSacado\", "); //28
		sb.append("nvl(fb.porc_mora, 0) AS \"porcentagemMora\", ");//29
		sb.append("nvl(fb.porc_multa, 0) AS \"porcentagemMulta\" ");//30
		
		writeFROMClause(sb, dataDe != null && dataAte != null, reenviar);
		
		Query query = getSession().createSQLQuery(sb.toString());
		query.setInteger(EMPRESA_ID, empresa.getEmpresaId());
		
		if(dataDe != null && dataAte != null){
			query.setDate(DATA_DE, dataDe);
			query.setDate(DATA_ATE, dataAte);
		}
		List<Object[]> list = query.list();
		
		ArquivoRemessa arquivoRemessa = new ArquivoRemessa(BancoLayout.SANTANDER_400_Envio);
		
		String nomeArquivo = "CB" + new SimpleDateFormat("ddMM").format(new Date());
		int variavel = 0;
		
		ArquivoRemessaItem arquivoRemessaItem = null;
		CabecalhoRemessaSantander cabecalhoRemessaSantander = null;
		
		for(Object[] tupla : list){
			
			Integer idRemessa = Integer.valueOf(tupla[1].toString());
			variavel = idRemessa;
			String codEmpresaBanco = tupla[2] != null ? tupla[2].toString() : "0";
			String nomeEmpresa = tupla[3].toString();
			Integer codigoTransmissao = tupla[26] != null ? Integer.valueOf(tupla[26].toString()) : 0;
			
			if(!tupla[8].toString().contains("-")){
				log.error("NossoNumero não está no formato correto: " + tupla[8].toString() + ". Ignorando o registro FechamentoBoletoId = " + tupla[0].toString());
				continue;
			}
					
			if(cabecalhoRemessaSantander == null){
				cabecalhoRemessaSantander = new CabecalhoRemessaSantander();
				cabecalhoRemessaSantander.setNumeroSequencialRemessa(idRemessa);
				cabecalhoRemessaSantander.setCodigoTransmissao(gerarCodigoTransmissao(tupla[4].toString(), tupla[27].toString(), codEmpresaBanco, tupla[5].toString(), tupla[6].toString()));
				cabecalhoRemessaSantander.setDataGravacao(new Date());
				cabecalhoRemessaSantander.setCodigoEmpresa(codEmpresaBanco);
				cabecalhoRemessaSantander.setNomeEmpresa(nomeEmpresa);
				
				arquivoRemessaItem = new ArquivoRemessaSantander();
				arquivoRemessaItem.setCabecalhoRemessa(cabecalhoRemessaSantander);
				arquivoRemessaItem.setRodapeRemessa(new RodapeRemessaPadrao());
				
				arquivoRemessa.addItem(arquivoRemessaItem);
				
			}else if(!cabecalhoRemessaSantander.getCodigoEmpresa().equals(codEmpresaBanco)){
				cabecalhoRemessaSantander = new CabecalhoRemessaSantander();
				cabecalhoRemessaSantander.setNumeroSequencialRemessa(idRemessa);
				cabecalhoRemessaSantander.setDataGravacao(new Date());
				cabecalhoRemessaSantander.setCodigoEmpresa(codEmpresaBanco);
				cabecalhoRemessaSantander.setNomeEmpresa(nomeEmpresa);
				
				arquivoRemessaItem = new ArquivoRemessaSantander();
				arquivoRemessaItem.setCabecalhoRemessa(cabecalhoRemessaSantander);
				arquivoRemessaItem.setRodapeRemessa(new RodapeRemessaPadrao());
				
				arquivoRemessa.addItem(arquivoRemessaItem);
			}
			
			DetalheObrigatorioSantander detalhe = new DetalheObrigatorioSantander();  
			
			String []doc = tupla[8].toString().split("-");		
			detalhe.setIdBoletoFechamento(Integer.valueOf(tupla[0].toString()));
			detalhe.setTipoInscricao(TipoInscricaoPagador.CNPJ);
			detalhe.setCodigoTransmissao(codigoTransmissao.toString());
			
			detalhe.setCarteira(tupla[7].toString());
			detalhe.setAgencia(tupla[4].toString());
			detalhe.setAgenciaCobradora(tupla[4].toString());
			detalhe.setContacorrente(tupla[5].toString());
			detalhe.setDvConta(tupla[6].toString());
			detalhe.setNumControleDoParticipante(tupla[0].toString());
			detalhe.setNossoNumeroComDigito(doc[0] + doc[1]);
			detalhe.setCodigoDeOcorrencia(0);
			detalhe.setDataOcorrencia(null);
			detalhe.setNumeroDoDocumento(doc[0] + doc[1]);
			detalhe.setVencimento((Date) tupla[9]);
			detalhe.setValor(new BigDecimal(tupla[10].toString().replaceAll(",", ".")));
			detalhe.setEspecieDeTitulo("01");
			detalhe.setEmissao((Date) tupla[12]);
			detalhe.setInstrucao1("00");
			detalhe.setInstrucao2("00");
			detalhe.setDataLimiteDesconto(null);
			detalhe.setDvAgencia(tupla[27].toString());
			detalhe.setCodigoEmpresa(codEmpresaBanco);
			detalhe.setCodigoTransmissao(gerarCodigoTransmissao(tupla[4].toString(), tupla[27].toString(), codEmpresaBanco, tupla[5].toString(), tupla[6].toString()));
			detalhe.setValorIOF(BigDecimal.ZERO);
			detalhe.setNomeSacado(tupla[20].toString());
			detalhe.setMensagem1("");
			detalhe.setSacadorAvalista("");
			detalhe.setPercentualMulta( (BigDecimal) tupla[30] );
			
			try{
				if( tupla[15] != null ) {
					detalhe.setValorAtraso(new BigDecimal(tupla[15].toString().replaceAll(",", ".")));
				}else if( tupla[29] != null ) {
					detalhe.setValorAtraso( calculaValorMora( (BigDecimal) tupla[29], new BigDecimal(tupla[10].toString().replaceAll(",", ".") ))  );
				}else {
					detalhe.setValorAtraso( BigDecimal.ZERO );
				}
				
			}catch(Exception e){
				throw new ValidacaoRemessaException("Erro ao setar o valor de atraso do boleto "+tupla[0]+", favor entrar em contato com o suporte! ");
			}
			
			try{
				detalhe.setValorDesconto(new BigDecimal(tupla[16].toString().replaceAll(",", ".")));
			}catch(Exception e){}
			
			try{
				detalhe.setValorAbatimentoConcedido(new BigDecimal(tupla[17].toString().replaceAll(",", ".")));
			}catch(Exception e){}
			
			try{
				detalhe.setNumeroInscricao(tupla[19].toString().replaceAll(NUMERAIS, ""));
			}catch(Exception e){
				throw new ValidacaoRemessaException("A inscrição do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setNumeroInscricaoSacado(tupla[28].toString().replaceAll(NUMERAIS, ""));
			}catch(Exception e){
				throw new ValidacaoRemessaException("O CNPJ do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setEnderecoSacado(tupla[21].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Endereco do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setBairroSacado(tupla[22].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Bairro do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setCidade(tupla[23].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("A Cidade do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setEstado(tupla[24].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Estado do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			try{
				String cep = tupla[25].toString();
				detalhe.setCepSacado(cep.substring(0,5));
				detalhe.setComplementoCepSacado(cep.substring(5));
			}catch(Exception e){
				throw new ValidacaoRemessaException("O CEP do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			arquivoRemessaItem.addTitulo(detalhe);
			
			arquivoRemessaItem.getRodapeRemessa().setNumeroSequencialRegistro(arquivoRemessa.getItens().size());
		}
		
		nomeArquivo = nomeArquivo + new DecimalFormat("##").format(variavel) + ".REM";
		arquivoRemessa.setNomeArquivo(nomeArquivo);
	
		return arquivoRemessa;
		
	}

	public ArquivoRemessa remessaMercantil(Empresa empresa, Date dataDe, Date dataAte, Boolean reenviar) throws Exception{
		
		StringBuilder sb = new StringBuilder();
		
		sb.append(" SELECT ");
		sb.append(" fb.FECHAMENTOBOLETO_ID AS \"id\", ");
		sb.append(" (NVL(fp.COUNT_REMESSA, 0) + 1)  AS \"idRemessa\", ");
		sb.append(" fp.COD_EMP_BANCO AS \"codEmpresaBanco\", ");
		sb.append(" emp.NOMBEMPRESA AS \"nomeEmpresa\", ");
		sb.append(" fp.BOLETO_BANCO_AGENCIA AS \"agencia\", ");
		sb.append(" fp.BOLETO_BANCO_CONTA AS \"conta\", "); 
		sb.append(" fp.BOLETO_BANCO_CONTA_DIGITO AS \"dac\", "); 
		sb.append(" fp.BOLETO_BANCO_CARTEIRA AS \"carteira\", ");
		sb.append(" fb.NOSSONUMERO AS \"nossoNumero\", ");
		sb.append(" fb.FECVENCIMENTO AS \"vencimento\", ");
		sb.append(" fb.VALORDOCUMENTO AS \"valor\", ");
		sb.append(" '01' AS \"especieTitulo\", ");
		sb.append(" fb.FECDOCUMENTO AS \"dataEmissao\", ");
		sb.append(" '00' AS \"instrucao1\", ");
		sb.append(" '00' AS \"instrucao2\", ");
		sb.append(" fb.MORA AS \"valorAtraso\", ");
		sb.append(" fb.DESCONTOS AS \"valorDesconto\", ");
		sb.append(" fb.DEDUCOES AS \"valorAbatimento\", ");
		sb.append(" 'cnpj' as \"tipoInscricaoPagador\", ");
		sb.append(" pv.NUMDOCPUNTOVENTA AS \"numeroInscricaoPagador\", ");
		sb.append(" pv.NOMBPUNTOVENTA AS \"nomePagador\", ");
		sb.append(" pv.DIRECCIONCALLE || ', ' || pv.DIRECCIONNUMERO as endereco,");
		sb.append(" pl.NOMBPLAZA as bairro, ");
		sb.append(" ci.NOMBCIUDAD  AS cidade, ");
		sb.append(" es.CVEESTADO AS estado, ");
		sb.append(" pv.CODPOSTAL AS \"cepPagador\", ");
		sb.append(" ecb.NUMINTEGRACION AS \"numeroContrato\" ");
		
		writeFROMClause(sb, dataDe != null && dataAte != null, reenviar);
		
		Query query = getSession().createSQLQuery(sb.toString());
		query.setInteger(EMPRESA_ID, empresa.getEmpresaId());
		
		if(dataDe != null && dataAte != null){
			query.setDate(DATA_DE, dataDe);
			query.setDate(DATA_ATE, dataAte);
		}
		List<Object[]> list = query.list();
		
		ArquivoRemessa arquivoRemessa = new ArquivoRemessa(BancoLayout.MERCANTIL_400_Envio);
		
		String nomeArquivo = "CB" + new SimpleDateFormat("ddMM").format(new Date());
		int variavel = 0;
		
		ArquivoRemessaItem arquivoRemessaItem = null;
		CabecalhoRemessaMercantil cabecalhoRemessaMercantil = null;
		
		for(Object[] tupla : list){
			
			Integer idRemessa = Integer.valueOf(tupla[1].toString());
			variavel = idRemessa;
			String codEmpresaBanco = tupla[2] != null ? tupla[2].toString() : "0";
			String nomeEmpresa = tupla[3].toString();
			
			if(!tupla[8].toString().contains("-")){
				log.error("NossoNumero não está no formato correto: " + tupla[8].toString() + ". Ignorando o registro FechamentoBoletoId = " + tupla[0].toString());
				continue;
			}
					
			if(cabecalhoRemessaMercantil == null){
				cabecalhoRemessaMercantil = new CabecalhoRemessaMercantil();
				cabecalhoRemessaMercantil.setNumeroSequencialRemessa(idRemessa);
				cabecalhoRemessaMercantil.setAgenciaOrigem(tupla[4].toString());
				cabecalhoRemessaMercantil.setCnpj(Long.valueOf(tupla[19].toString().replaceAll(NUMERAIS, "")));
				cabecalhoRemessaMercantil.setDataGravacao(new Date());
				cabecalhoRemessaMercantil.setCodigoEmpresa(codEmpresaBanco);
				cabecalhoRemessaMercantil.setNomeEmpresa(nomeEmpresa);
				
				arquivoRemessaItem = new ArquivoRemessaMercantil();
				arquivoRemessaItem.setCabecalhoRemessa(cabecalhoRemessaMercantil);
				arquivoRemessaItem.setRodapeRemessa(new RodapeRemessaPadrao());
				
				arquivoRemessa.addItem(arquivoRemessaItem);
				
			}else if(!cabecalhoRemessaMercantil.getCodigoEmpresa().equals(codEmpresaBanco)){
				cabecalhoRemessaMercantil = new CabecalhoRemessaMercantil();
				cabecalhoRemessaMercantil.setNumeroSequencialRemessa(idRemessa);
				cabecalhoRemessaMercantil.setDataGravacao(new Date());
				cabecalhoRemessaMercantil.setCodigoEmpresa(codEmpresaBanco);
				cabecalhoRemessaMercantil.setNomeEmpresa(nomeEmpresa);
				
				arquivoRemessaItem = new ArquivoRemessaMercantil();
				arquivoRemessaItem.setCabecalhoRemessa(cabecalhoRemessaMercantil);
				arquivoRemessaItem.setRodapeRemessa(new RodapeRemessaPadrao());
				
				arquivoRemessa.addItem(arquivoRemessaItem);
			}
			
			DetalheObrigatorioMercantil detalhe = new DetalheObrigatorioMercantil();  
			
			String []doc = tupla[8].toString().split("-");		
			detalhe.setIdBoletoFechamento(Integer.valueOf(tupla[0].toString()));
			detalhe.setNumeroContrato(Integer.valueOf(tupla[26].toString()));
			detalhe.setAgenciaOrigem(tupla[4].toString());
			detalhe.setSeuNumero(Integer.valueOf(tupla[0].toString()));
			detalhe.setNossoNumero(doc[0]);
			detalhe.setDigitoVerificador(doc[1]);
			detalhe.setCodigoDeOcorrencia(0);
			detalhe.setDataOcorrencia(null);
			detalhe.setNumeroDoDocumento(StringUtils.right(doc[0], 10));
			detalhe.setVencimento((Date) tupla[9]);
			detalhe.setValorTitulo(new BigDecimal(tupla[10].toString().replaceAll(",", ".")));
			detalhe.setEspecieDeTitulo(tupla[11].toString());
			detalhe.setEmissao((Date) tupla[12]);
			detalhe.setInstrucao1(tupla[13].toString());
			detalhe.setInstrucao2(tupla[14].toString());
			detalhe.setDataLimiteDesconto(null);
			detalhe.setMensagem1("");
			detalhe.setSacadorAvalistaMensagem2("");
			detalhe.setValorIOF(BigDecimal.ZERO);
			detalhe.setNomePagador(tupla[20].toString());
			
			try{
				detalhe.setValorAtraso(new BigDecimal(tupla[15].toString().replaceAll(",", ".")));
			}catch(Exception e){}
			
			try{
				detalhe.setValorDesconto(new BigDecimal(tupla[16].toString().replaceAll(",", ".")));
			}catch(Exception e){}
			
			try{
				detalhe.setValorAbatimentoConcedido(new BigDecimal(tupla[17].toString().replaceAll(",", ".")));
			}catch(Exception e){}
			
			
			try{
				detalhe.setEnderecoCompletoPagador(tupla[21].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Endereço do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setBairro(tupla[22].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Bairro do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setCidade(tupla[23].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("A cidade do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setEstado(tupla[24].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Estado do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setCnpj(Long.valueOf(tupla[19].toString().replaceAll(NUMERAIS, "")));
			}catch(Exception e){
				throw new ValidacaoRemessaException("O CNPJ do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			try{
				String cep = tupla[25].toString();
				detalhe.setCepPrefixo(cep.substring(0,5));
				detalhe.setCepSufixo(cep.substring(5));
			}catch(Exception e){
				throw new ValidacaoRemessaException("O CEP do ponto de venda "+tupla[20]+" está fora do padrão, favor corrigir");
			}
			
			arquivoRemessaItem.addTitulo(detalhe);
			
			arquivoRemessaItem.getRodapeRemessa().setNumeroSequencialRegistro(arquivoRemessa.getItens().size());
			
		}
		
		nomeArquivo = nomeArquivo + new DecimalFormat("##").format(variavel) + ".REM";
		arquivoRemessa.setNomeArquivo(nomeArquivo);
	
		return arquivoRemessa;
		
	}
	
	@Override
	public ArquivoRemessa remessaItau(Empresa empresa, Date dataDe, Date dataAte, Boolean reenviar) throws Exception {
		
		StringBuilder sb = new StringBuilder();
		
		sb.append("SELECT ");
		sb.append("fb.FECHAMENTOBOLETO_ID AS \"id\", ");
		sb.append("(NVL(fp.COUNT_REMESSA, 0) + 1)  AS \"idRemessa\", ");
		sb.append("fp.COD_EMP_BANCO AS \"codEmpresaBanco\", ");
		sb.append("emp.CNPJ AS \"cnpj\", ");
		sb.append("emp.NOMBEMPRESA AS \"nomeEmpresa\", ");
		sb.append("fp.BOLETO_BANCO_AGENCIA AS \"agencia\", ");
		sb.append("fp.BOLETO_BANCO_CONTA AS \"conta\", "); 
		sb.append("fp.BOLETO_BANCO_CONTA_DIGITO AS \"dac\", "); 
		sb.append("fp.BOLETO_BANCO_CARTEIRA AS \"carteira\", ");
		sb.append("fb.NOSSONUMERO AS \"nossoNumero\", ");
		sb.append("fb.FECVENCIMENTO AS \"vencimento\", ");
		sb.append("fb.VALORDOCUMENTO AS \"valor\", ");
		sb.append("99 AS \"especieTitulo\", ");
		sb.append("fb.FECDOCUMENTO AS \"dataEmissao\", ");
		sb.append("' ' AS \"instrucao1\", ");
		sb.append("' ' AS \"instrucao2\", ");
		sb.append("fb.MORA AS \"valorAtraso\", ");
		sb.append("fb.DESCONTOS AS \"valorDesconto\", ");
		sb.append("fb.DEDUCOES AS \"valorAbatimento\", ");
		sb.append("'cnpj' as \"tipoInscricaoPagador\", ");
		sb.append("pv.NUMDOCPUNTOVENTA AS \"numeroInscricaoPagador\", ");
		sb.append("pv.NOMBPUNTOVENTA AS \"nomePagador\", ");
		sb.append("pv.DIRECCIONCALLE || ', ' || pv.DIRECCIONNUMERO AS \"logradouroPagador\", ");
		sb.append("pl.NOMBPLAZA AS \"bairroPagador\", ");
		sb.append("pv.CODPOSTAL AS \"cepPagador\", ");
		sb.append("ci.NOMBCIUDAD AS \"cidadePagador\", ");
		sb.append("es.cveestado AS \"estadoPagador\", ");
		sb.append("nvl(fb.porc_mora, 0) AS \"porcentagemMora\", ");
		sb.append("nvl(fb.porc_multa, 0) AS \"porcentagemMulta\" ");
		writeFROMClause(sb, dataDe != null && dataAte != null, reenviar);
		
		Query query = getSession().createSQLQuery(sb.toString());
		query.setInteger(EMPRESA_ID, empresa.getEmpresaId());
		if(dataDe != null && dataAte != null){
			query.setDate(DATA_DE, dataDe);
			query.setDate(DATA_ATE, dataAte);
		}
		List<Object[]> list = query.list();
		
		ArquivoRemessa arquivoRemessa = new ArquivoRemessa(BancoLayout.ITAU_400_Envio);
		
		String nomeArquivo = "RE" + new SimpleDateFormat("ddMM").format(new Date());
		int variavel = 0;
		int contador = 1;
		
		ArquivoRemessaItem arquivoRemessaItem = null;
		CabecalhoRemessaItau cabecalhoRemessaItau = null;
		
		for(Object[] tupla : list){
			
			Integer idRemessa = Integer.valueOf(tupla[1].toString());
			variavel = idRemessa;
			Integer codEmpresaBanco = Integer.valueOf(tupla[5].toString() + tupla[6].toString());
			String nomeEmpresa = tupla[4].toString();
			
			if(cabecalhoRemessaItau == null){
				cabecalhoRemessaItau = new CabecalhoRemessaItau();
				cabecalhoRemessaItau.setNumeroSequencialRemessa(idRemessa);
				cabecalhoRemessaItau.setNumeroSequencialRegistro(contador);
				cabecalhoRemessaItau.setDataGeracao(new Date());
				cabecalhoRemessaItau.setAgencia(Integer.valueOf(tupla[5].toString()));
				cabecalhoRemessaItau.setConta(Integer.valueOf(tupla[6].toString()));
				cabecalhoRemessaItau.setDacConta(Integer.valueOf(tupla[7].toString()));
				cabecalhoRemessaItau.setNomeEmpresa(nomeEmpresa);
				
				arquivoRemessaItem = new ArquivoRemessaItau();
				arquivoRemessaItem.setCabecalhoRemessa(cabecalhoRemessaItau);
				arquivoRemessaItem.setRodapeRemessa(new RodapeRemessaPadrao());
				
				arquivoRemessa.addItem(arquivoRemessaItem);
			}			
			
			DetalheObrigatorioItau detalhe = new DetalheObrigatorioItau();  
			
			String []doc = tupla[9].toString().split("-");
			
			detalhe.setIdBoletoFechamento(Integer.valueOf(tupla[0].toString()));
			detalhe.setNumeroInscricao(codEmpresaBanco);
			detalhe.setAgencia(Integer.valueOf(tupla[5].toString()));
			detalhe.setConta(Integer.valueOf(tupla[6].toString()));
			detalhe.setDacConta(Integer.valueOf(tupla[7].toString()));
			detalhe.setInstrucaoAlegacao(0000);
			detalhe.setNossoNumero(Integer.valueOf(doc[0]));
			detalhe.setNumCpfCnpj(tupla[3].toString());
			detalhe.setQtdMoeda(BigDecimal.ZERO);
			detalhe.setNrCarteira(Integer.valueOf(tupla[8].toString()));
			detalhe.setCodigoDeOcorrencia(01);
			detalhe.setNumeroDoDocumento(tupla[0].toString());
			detalhe.setVencimento((Date) tupla[10]);
			detalhe.setValor(new BigDecimal(tupla[11].toString().replace(",", ".")));
			detalhe.setAgenciaCobradora(0);
			detalhe.setEspecieDeTitulo("99");
			detalhe.setAceite("A");
			detalhe.setEmissao((Date) tupla[13]);
			detalhe.setInstrucao1("05");
			detalhe.setInstrucao1("00");
			detalhe.setDataDesconto(null);
			detalhe.setIOF_Devido(BigDecimal.ZERO);
			detalhe.setNomeSacado(tupla[21].toString());
			detalhe.setTipoInscricaoSacado(TipoInscricaoPagador.CNPJ);			
			detalhe.setPrazo(00);
			detalhe.setNumeroSequencialRegistro(++contador);
			detalhe.setSacadorAvalista(tupla[21].toString());
			
			try{
				BigDecimal percentualMulta = new BigDecimal(tupla[28].toString().replace(",", "."));
				if( percentualMulta.compareTo(BigDecimal.ZERO) > 0) {
					DetalheMulta multa = new DetalheMulta();
					multa.setCodigoMulta("2");
					multa.setDataMulta(DateUtil.somarDias((Date) tupla[10], 1));
					multa.setPercentualMulta(percentualMulta);
					multa.setNumeroSequencial(++contador);
					detalhe.setDetalheMulta(multa);
				}
			}catch(Exception e){
				log.error("Erro ao gerar detalhe muulta para remessaId=" + tupla[1].toString() , e);
			}
			
			try{
				detalhe.setJurosDeMora(new BigDecimal(tupla[27].toString().replace(",", ".")));	
				detalhe.setDataDeMora(DateUtil.somarDias((Date) tupla[10], 1));
			}catch(Exception e){
				detalhe.setJurosDeMora(BigDecimal.ZERO);
				detalhe.setDataDeMora(null);
			}
			
			try{
				detalhe.setDescontoConcedido(new BigDecimal(tupla[17].toString().replace(",", ".")));
			}catch(Exception e){
				detalhe.setDescontoConcedido(BigDecimal.ZERO);
			}
			
			try{
				detalhe.setAbatimentoConcedido(new BigDecimal(tupla[18].toString().replace(",", ".")));
			}catch(Exception e){
				detalhe.setAbatimentoConcedido(BigDecimal.ZERO);
			}
			
			try{
				detalhe.setNumeroInscricaoSacado(Long.valueOf(tupla[20].toString()));
			}catch(Exception e){
				throw new ValidacaoRemessaException("O CNPJ do ponto de venda "+tupla[21]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setLogradouroSacado(tupla[22].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Logradouro do ponto de venda "+tupla[21]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setBairroSacado(tupla[23].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Bairro do ponto de venda "+tupla[21]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setCepSacado(tupla[24].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O CEP do ponto de venda "+tupla[21]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setCidade(tupla[25].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("A cidade do ponto de venda "+tupla[21]+" está fora do padrão, favor corrigir");
			}
			
			try{
				detalhe.setEstado(tupla[26].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Estado do ponto de venda "+tupla[21]+" está fora do padrão, favor corrigir");
			}			

			arquivoRemessaItem.addTitulo(detalhe);	
		}
		if(arquivoRemessaItem!=null && arquivoRemessaItem.getRodapeRemessa()!=null) {
			arquivoRemessaItem.getRodapeRemessa().setNumeroSequencialRegistro(++contador);
		}
		nomeArquivo = nomeArquivo + new DecimalFormat("##").format(variavel) + ".REM";
		arquivoRemessa.setNomeArquivo(nomeArquivo);
	
		return arquivoRemessa;
	}
	
	@Override
	public ArquivoRemessa remessaBancoBrasil(Empresa empresa, Date dataDe, Date dataAte, Boolean reenviar) throws Exception {
		
		StringBuilder sb = new StringBuilder();
		
		sb.append("SELECT ");
		sb.append("fb.FECHAMENTOBOLETO_ID AS \"id\", ");
		sb.append("(NVL(fp.COUNT_REMESSA, 0) + 1)  AS \"idRemessa\", ");
		sb.append("fp.COD_EMP_BANCO AS \"codEmpresaBanco\", ");
		sb.append("emp.CNPJ AS \"cnpj\", ");
		sb.append("emp.NOMBEMPRESA AS \"nomeEmpresa\", ");
		sb.append("fp.BOLETO_BANCO_AGENCIA AS \"agencia\", ");
		sb.append("fp.BOLETO_BANCO_CONTA AS \"conta\", "); 
		sb.append("fp.BOLETO_BANCO_CONTA_DIGITO AS \"dac\", "); 
		sb.append("fp.BOLETO_BANCO_CARTEIRA AS \"carteira\", ");
		sb.append("fb.NOSSONUMERO AS \"nossoNumero\", ");
		sb.append("fb.FECVENCIMENTO AS \"vencimento\", ");
		sb.append("fb.VALORDOCUMENTO AS \"valor\", ");
		sb.append("99 AS \"especieTitulo\", ");
		sb.append("fb.FECDOCUMENTO AS \"dataEmissao\", ");
		sb.append("' ' AS \"instrucao1\", ");
		sb.append("' ' AS \"instrucao2\", ");
		sb.append("fb.MORA AS \"valorAtraso\", ");
		sb.append("fb.DESCONTOS AS \"valorDesconto\", ");
		sb.append("fb.DEDUCOES AS \"valorAbatimento\", ");
		sb.append("'cnpj' as \"tipoInscricaoPagador\", ");
		sb.append("pv.NUMDOCPUNTOVENTA AS \"numeroInscricaoPagador\", ");
		sb.append("pv.NOMBPUNTOVENTA AS \"nomePagador\", ");
		sb.append("pv.DIRECCIONCALLE || ', ' || pv.DIRECCIONNUMERO AS \"logradouroPagador\", ");
		sb.append("pl.NOMBPLAZA AS \"bairroPagador\", ");
		sb.append("pv.CODPOSTAL AS \"cepPagador\", ");
		sb.append("ci.NOMBCIUDAD AS \"cidadePagador\", ");
		sb.append("es.NOMBESTADO AS \"estadoPagador\", ");
		sb.append("fp.BOLETO_BANCO_AGENCIA_DIGITO AS \"digitoAgencia\", ");
		sb.append("fp.BOLETO_BANCO_CARTEIRA_VARIAVEL AS \"variavelCarteira\" ");
		writeFROMClause(sb, dataDe != null && dataAte != null, reenviar);
		
		Query query = getSession().createSQLQuery(sb.toString());
		query.setInteger(EMPRESA_ID, empresa.getEmpresaId());
		if(dataDe != null && dataAte != null){
			query.setDate(DATA_DE, dataDe);
			query.setDate(DATA_ATE, dataAte);
		}
		List<Object[]> list = query.list();
		
		ArquivoRemessa arquivoRemessa = new ArquivoRemessa(BancoLayout.BB_240_Envio);
		
		String nomeArquivo = "BB" + new SimpleDateFormat("ddMM").format(new Date());
		int variavel = 0;
		
		
		ArquivoRemessaItem arquivoRemessaItem = null;
		CabecalhoRemessaBancoBrasil cabecalhoRemessaBancoBrasil = null;
		CabecalhoLoteRemessaBancoBrasil cabecalhoLoteRemessaBancoBrasil = null;
		RodapeRemessaLoteBancoBrasil rodapeRemessaLoteBancoBrasil = null;
		RodapeRemessaBancoBrasil rodapeRemessaBancoBrasil = null;
		
		for(Object[] tupla : list){
			
			Integer idRemessa = Integer.valueOf(tupla[1].toString());
			variavel = idRemessa;
			String codEmpresaBanco = ((BigDecimal) tupla[2]).toString();
			codEmpresaBanco = StringUtils.right("000000000" + codEmpresaBanco, 9);
			String nomeEmpresa = tupla[4].toString();
			
			DateFormat df = new SimpleDateFormat("HHmmss");
			
			if(cabecalhoRemessaBancoBrasil == null ||
					!(cabecalhoRemessaBancoBrasil.getNumConvenio()).equals(codEmpresaBanco)){
				cabecalhoRemessaBancoBrasil = new CabecalhoRemessaBancoBrasil();
				cabecalhoRemessaBancoBrasil.setNumeroSequencialRemessa(idRemessa);
				cabecalhoRemessaBancoBrasil.setDataGeracao(new Date());
				cabecalhoRemessaBancoBrasil.setHoraGeracao(Integer.parseInt(df.format(new Date())));
				cabecalhoRemessaBancoBrasil.setCpfCnpj(Integer.parseInt(TipoInscricaoPagador.CNPJ.getId()));
				cabecalhoRemessaBancoBrasil.setNumCpfCnpj(tupla[3].toString());
				cabecalhoRemessaBancoBrasil.setDensidadeArquivo("00000");
				cabecalhoRemessaBancoBrasil.setNumAgencia(tupla[5].toString());
				cabecalhoRemessaBancoBrasil.setDigAgencia(((BigDecimal) tupla[27]).toString());
				cabecalhoRemessaBancoBrasil.setDigAgenciaConta(" ");
				cabecalhoRemessaBancoBrasil.setNumContaCorrente(tupla[6].toString());
				cabecalhoRemessaBancoBrasil.setDigContaCorrente(tupla[7].toString());
				cabecalhoRemessaBancoBrasil.setNumCarteira(tupla[8].toString());
				cabecalhoRemessaBancoBrasil.setNomeEmpresa(nomeEmpresa);
				cabecalhoRemessaBancoBrasil.setNumConvenio(codEmpresaBanco);
				
				cabecalhoLoteRemessaBancoBrasil = new CabecalhoLoteRemessaBancoBrasil();
				cabecalhoLoteRemessaBancoBrasil.setCpfCnpj(Integer.parseInt(TipoInscricaoPagador.CNPJ.getId()));
				cabecalhoLoteRemessaBancoBrasil.setNumCpfCnpj(tupla[3].toString());
				cabecalhoLoteRemessaBancoBrasil.setNumAgencia(tupla[5].toString());
				cabecalhoLoteRemessaBancoBrasil.setDigAgencia(((BigDecimal) tupla[27]).toString());
				cabecalhoLoteRemessaBancoBrasil.setDigAgenciaConta(" ");
				cabecalhoLoteRemessaBancoBrasil.setNumContaCorrente(tupla[6].toString());
				cabecalhoLoteRemessaBancoBrasil.setDigContaCorrente(tupla[7].toString());
				cabecalhoLoteRemessaBancoBrasil.setNumCarteira(tupla[8].toString());				
				cabecalhoLoteRemessaBancoBrasil.setNomeEmpresa(nomeEmpresa);
				cabecalhoLoteRemessaBancoBrasil.setNumConvenio(codEmpresaBanco);
				cabecalhoLoteRemessaBancoBrasil.setDataGeracao(new Date());
				cabecalhoLoteRemessaBancoBrasil.setNumeroRemessa(idRemessa);
				
				try{
					cabecalhoRemessaBancoBrasil.setNumVarCarteira(((BigDecimal) tupla[28]).toString());
					cabecalhoLoteRemessaBancoBrasil.setNumVarCarteira(((BigDecimal) tupla[28]).toString());
				}catch(Exception e){
					throw new ValidacaoRemessaException(
							 String.format(
							  "A Variação Carteira da empresa %s está fora do padrão, favor corrigir",
							  nomeEmpresa)
							);
				}
				
				cabecalhoRemessaBancoBrasil.setCabecalhoLoteRemessaBancoBrasil(cabecalhoLoteRemessaBancoBrasil);
				
				arquivoRemessaItem = new ArquivoRemessaBancoBrasil();
				arquivoRemessaItem.setCabecalhoRemessa(cabecalhoRemessaBancoBrasil);
				
				arquivoRemessa.addItem(arquivoRemessaItem);
			}
			
			String []doc = tupla[9].toString().split("-");
			
			DetalheObrigatorioDadosTitulosBancoBrasil titulosBancoBrasil = new DetalheObrigatorioDadosTitulosBancoBrasil();
			titulosBancoBrasil.setIdBoletoFechamento(Integer.valueOf(tupla[0].toString()));
			titulosBancoBrasil.setNumAgencia(tupla[5].toString());
			titulosBancoBrasil.setDigAgencia(((BigDecimal) tupla[27]).toString());
			titulosBancoBrasil.setNumContaCorrente(tupla[6].toString());
			titulosBancoBrasil.setDigContaCorrente(tupla[7].toString());
			titulosBancoBrasil.setDigAgenciaConta(" ");
			titulosBancoBrasil.setNossoNumeroBB(doc[0]);
			titulosBancoBrasil.setCodCarteira(7);
			titulosBancoBrasil.setFormaCadTituloBanco(" ");
			titulosBancoBrasil.setTipoDocumento(" ");
			titulosBancoBrasil.setIdentEmissaoBloqueto(" ");
			titulosBancoBrasil.setIdentDistribuicao(" ");
			titulosBancoBrasil.setNumeroDoDocumento(tupla[0].toString());
			titulosBancoBrasil.setVencimento((Date) tupla[10]);
			titulosBancoBrasil.setValor(new BigDecimal(tupla[11].toString().replace(",", ".")));
			titulosBancoBrasil.setAgenciaCobradora(null);
			titulosBancoBrasil.setDigAgenciaCobradora(null);
			titulosBancoBrasil.setAceite(Aceite.NAO_ACEITE);
			titulosBancoBrasil.setEmissao((Date) tupla[13]);
			try{
				titulosBancoBrasil.setCodMora(1);
				titulosBancoBrasil.setJurosDeMora(new BigDecimal(tupla[16].toString().replace(",", ".")));
				titulosBancoBrasil.setDataMora((Date) tupla[10]);
			}catch(NullPointerException e){
				titulosBancoBrasil.setCodMora(1);
				titulosBancoBrasil.setDataMora((Date) tupla[10]);
				titulosBancoBrasil.setJurosDeMora(BigDecimal.ZERO);
			}
			
			try{
				BigDecimal desconto = new BigDecimal(tupla[17].toString().replace(",", "."));
				if(desconto.equals(BigDecimal.ZERO)) {
					zerarDesconto(titulosBancoBrasil);
				}
				
				titulosBancoBrasil.setCodigoDesconto(1);
				titulosBancoBrasil.setDataDesconto((Date) tupla[10]);
				titulosBancoBrasil.setDescontoConcedido(desconto);
			}catch(NullPointerException e){
				zerarDesconto(titulosBancoBrasil);
			}
			
			titulosBancoBrasil.setIOF_Devido(BigDecimal.ZERO);
			try{
				titulosBancoBrasil.setAbatimentoConcedido(new BigDecimal(tupla[18].toString().replace(",", ".")));
			}catch(NullPointerException e){
				titulosBancoBrasil.setAbatimentoConcedido(BigDecimal.ZERO);
			}
			
			titulosBancoBrasil.setNossoNumeroEmp("");
			titulosBancoBrasil.setCodigoProtesto(3);
			titulosBancoBrasil.setDiasProtesto(0);
			titulosBancoBrasil.setCodigoBaixa(2);
			titulosBancoBrasil.setDiasBaixa(0);
			titulosBancoBrasil.setNumeroContrato(0);
			
			DetalheObrigatorioDadosPagadorBancoBrasil pagadorBancoBrasil = new DetalheObrigatorioDadosPagadorBancoBrasil();
			pagadorBancoBrasil.setTipoInscricaoSacado(Integer.parseInt(TipoInscricaoPagador.CNPJ.getId()));			
			String ptoVenda = tupla[21].toString();
			pagadorBancoBrasil.setNomeSacado(ptoVenda);
			String cep = "";
			try{
				cep = StringUtils.right(ZERO_ESQUERDA + tupla[24].toString(), 8);
			}catch(Exception e){
				cep = ZERO_ESQUERDA;
			}
			int cepPrefix = Integer.parseInt(cep.substring(0, 5));
			int cepSufix = Integer.parseInt(cep.substring(5));
			pagadorBancoBrasil.setCepSacado(cepPrefix);
			pagadorBancoBrasil.setSufixoCep(cepSufix);
			pagadorBancoBrasil.setNossoNumeroNoBancoCorresp("");
			
			try{
				pagadorBancoBrasil.setNumeroInscricaoSacado(tupla[20].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException(
						 String.format(
						  "O CNPJ do ponto de venda %s está fora do padrão, favor corrigir",
						  ptoVenda)
						);
			}
			
			try{
				pagadorBancoBrasil.setLogradouroSacado(tupla[22].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException(
						 String.format(
						  "O Logradouro do ponto de venda %s está fora do padrão, favor corrigir",
						  ptoVenda)
						);
			}
			
			try{
				pagadorBancoBrasil.setBairroSacado(tupla[23].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException(
						 String.format(
						  "O Bairro do ponto de venda %s está fora do padrão, favor corrigir",
						  ptoVenda)
						);
			}
			
			try{
				pagadorBancoBrasil.setCidade(tupla[25].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException(
						 String.format(
						  "A cidade do ponto de venda %s está fora do padrão, favor corrigir",
						  ptoVenda)
						);
			}
			
			try{
				pagadorBancoBrasil.setEstado(tupla[26].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException(
						 String.format(
						  "O Estado do ponto de venda %s está fora do padrão, favor corrigir",
						  ptoVenda)
						);
			}

			titulosBancoBrasil.setDetalheObrigatorioDadosPagadorBancoBrasil(pagadorBancoBrasil);
			
			arquivoRemessaItem.addTitulo(titulosBancoBrasil);
			
		}
		
		if(true && arquivoRemessaItem != null){
			rodapeRemessaLoteBancoBrasil = new RodapeRemessaLoteBancoBrasil();
			//rodapeRemessaLoteBancoBrasil.setLoteServico(loteCount);
			
			rodapeRemessaBancoBrasil = new RodapeRemessaBancoBrasil();
			//rodapeRemessaBancoBrasil.setLoteServico(9999);
			rodapeRemessaBancoBrasil.setQtdContas(0);
			
			rodapeRemessaBancoBrasil.setRodapeRemessaLoteBancoBrasil(rodapeRemessaLoteBancoBrasil);
			
			arquivoRemessaItem.setRodapeRemessa(rodapeRemessaBancoBrasil);
		}
		
		nomeArquivo = nomeArquivo + new DecimalFormat("##").format(variavel) + ".REM";
		arquivoRemessa.setNomeArquivo(nomeArquivo);
		
		return arquivoRemessa;
	}
	
	@Override
	public ArquivoRemessa remessaSicoob(Empresa empresa, Date dataDe, Date dataAte, Boolean reenviar) throws Exception {
		
		StringBuilder sb = new StringBuilder();
		
		sb.append("SELECT ");
		sb.append("fb.FECHAMENTOBOLETO_ID AS \"id\", ");
		sb.append("(NVL(fp.COUNT_REMESSA, 1) + 1)  AS \"idRemessa\", ");
		sb.append("fp.COD_EMP_BANCO AS \"codEmpresaBanco\", ");
		sb.append("emp.CNPJ AS \"cnpj\", ");
		sb.append("emp.NOMBEMPRESA AS \"nomeEmpresa\", ");
		sb.append("fp.BOLETO_BANCO_AGENCIA AS \"agencia\", ");
		sb.append("fp.BOLETO_BANCO_CONTA AS \"conta\", "); 
		sb.append("fp.BOLETO_BANCO_CONTA_DIGITO AS \"dac\", "); 
		sb.append("fp.BOLETO_BANCO_CARTEIRA AS \"carteira\", ");
		sb.append("fb.NOSSONUMERO AS \"nossoNumero\", ");
		sb.append("fb.FECVENCIMENTO AS \"vencimento\", ");
		sb.append("fb.VALORDOCUMENTO AS \"valor\", ");
		sb.append("99 AS \"especieTitulo\", ");
		sb.append("fb.FECDOCUMENTO AS \"dataEmissao\", ");
		sb.append("' ' AS \"instrucao1\", ");
		sb.append("' ' AS \"instrucao2\", ");
		sb.append("fb.MORA AS \"valorAtraso\", ");
		sb.append("fb.DESCONTOS AS \"valorDesconto\", ");
		sb.append("fb.DEDUCOES AS \"valorAbatimento\", ");
		sb.append("'cnpj' as \"tipoInscricaoPagador\", ");
		sb.append("pv.NUMDOCPUNTOVENTA AS \"numeroInscricaoPagador\", ");
		sb.append("pv.NOMBPUNTOVENTA AS \"nomePagador\", ");
		sb.append("pv.DIRECCIONCALLE || ', ' || pv.DIRECCIONNUMERO AS \"logradouroPagador\", ");
		sb.append("pl.NOMBPLAZA AS \"bairroPagador\", ");
		sb.append("pv.CODPOSTAL AS \"cepPagador\", ");
		sb.append("ci.NOMBCIUDAD AS \"cidadePagador\", ");
		sb.append("es.NOMBESTADO AS \"estadoPagador\", ");
		sb.append("fp.BOLETO_BANCO_AGENCIA_DIGITO AS \"digitoAgencia\", ");
		sb.append("fp.BOLETO_BANCO_CARTEIRA_VARIAVEL AS \"variavelCarteira\", ");
		sb.append("es.CVEESTADO AS \"cveEstado\" ");
		writeFROMClause(sb, dataDe != null && dataAte != null, reenviar);
		
		Query query = getSession().createSQLQuery(sb.toString());
		query.setInteger(EMPRESA_ID, empresa.getEmpresaId());
		if(dataDe != null && dataAte != null){
			query.setDate(DATA_DE, dataDe);
			query.setDate(DATA_ATE, dataAte);
		}
		List<Object[]> list = query.list();
		
		ArquivoRemessa arquivoRemessa = new ArquivoRemessa(BancoLayout.SICOOB_240_Envio);
		
		String nomeArquivo = "Sicoob" + new SimpleDateFormat("ddMM").format(new Date());
		int variavel = 0;
		int seqRegistro = 1;
		int qtdeTitulos = 0;
		BigDecimal valorTitulos = BigDecimal.ZERO;
			
		ArquivoRemessaItem arquivoRemessaItem = null;
		CabecalhoRemessaSicoob cabecalhoRemessaSicoob = null;
		CabecalhoLoteRemessaSicoob cabecalhoLoteRemessaSicoob = null;
		RodapeRemessaLoteSicoob rodapeRemessaLoteSicoob = null;
		RodapeRemessaSicoob rodapeRemessaSicoob = null;
		
		for(Object[] tupla : list){
			
			Integer idRemessa = Integer.valueOf(tupla[1].toString());
			variavel = idRemessa;
			String codEmpresaBanco = tupla[2] == null ? "" : ((BigDecimal) tupla[2]).toString();
			codEmpresaBanco = StringUtils.right("000000000" + codEmpresaBanco, 9);
			String nomeEmpresa = tupla[4].toString();
			BigDecimal valor = new BigDecimal(tupla[11].toString().replace(",", "."));
			
			qtdeTitulos++;
			valorTitulos.add( valor );
			
			if(cabecalhoRemessaSicoob == null ){
				cabecalhoRemessaSicoob = new CabecalhoRemessaSicoob();
				cabecalhoRemessaSicoob.setNumeroSequencialRemessa(idRemessa);
				cabecalhoRemessaSicoob.setCpfCnpj(Integer.parseInt(TipoInscricaoPagador.CNPJ.getId()));
				cabecalhoRemessaSicoob.setNumCpfCnpj(tupla[3].toString());
				cabecalhoRemessaSicoob.setNumAgencia(tupla[5].toString());
				cabecalhoRemessaSicoob.setDigAgencia(((BigDecimal) tupla[27]).toString());				
				cabecalhoRemessaSicoob.setNumContaCorrente(tupla[6].toString());
				cabecalhoRemessaSicoob.setDigContaCorrente(tupla[7].toString());				
				cabecalhoRemessaSicoob.setNomeEmpresa(nomeEmpresa);				
				cabecalhoRemessaSicoob.setNumRemessa(idRemessa);
				cabecalhoRemessaSicoob.setDataGravacao(new Date());	 
				cabecalhoRemessaSicoob.setNumConvenio(codEmpresaBanco);
				
				cabecalhoLoteRemessaSicoob = new CabecalhoLoteRemessaSicoob();
				cabecalhoLoteRemessaSicoob.setCpfCnpj(Integer.parseInt(TipoInscricaoPagador.CNPJ.getId()));
				cabecalhoLoteRemessaSicoob.setNumCpfCnpj(tupla[3].toString());
				cabecalhoLoteRemessaSicoob.setNumAgencia(tupla[5].toString());
				cabecalhoLoteRemessaSicoob.setDigAgencia(((BigDecimal) tupla[27]).toString());				
				cabecalhoLoteRemessaSicoob.setNumContaCorrente(tupla[6].toString());
				cabecalhoLoteRemessaSicoob.setDigContaCorrente(tupla[7].toString());
				cabecalhoLoteRemessaSicoob.setNomeEmpresa(nomeEmpresa);
				cabecalhoLoteRemessaSicoob.setNumeroRemessa(idRemessa);
				cabecalhoLoteRemessaSicoob.setDataGeracao(new Date());				
				cabecalhoRemessaSicoob.setCabecalhoLoteRemessaSicoob(cabecalhoLoteRemessaSicoob);
				
				arquivoRemessaItem = new ArquivoRemessaSicoob();
				arquivoRemessaItem.setCabecalhoRemessa(cabecalhoRemessaSicoob);
				
				arquivoRemessa.addItem(arquivoRemessaItem);
			}else {
				try{
					if( !(cabecalhoRemessaSicoob.getNumConvenio()).equals(codEmpresaBanco)) {
						throw new ValidacaoRemessaException(Labels.getLabel("relatorioRemessaCNAB.exception.ValidacaoRemessaConvenioException"));						
					}						
				}catch(Exception e){
					throw new ValidacaoRemessaException(Labels.getLabel("relatorioRemessaCNAB.exception.ValidacaoRemessaMontagemCabecalhoException"));						
				}
			}
			
			String []doc = tupla[9].toString().split("-");
			
			DetalheObrigatorioSicoob titulosSicoob = new DetalheObrigatorioSicoob();
			titulosSicoob.setIdBoletoFechamento(Integer.valueOf(tupla[0].toString()));
			titulosSicoob.setNumSeqRegistro( seqRegistro++ );
			titulosSicoob.setNumAgencia(tupla[5].toString());
			titulosSicoob.setDigAgencia(((BigDecimal) tupla[27]).toString());
			titulosSicoob.setNumContaCorrente(tupla[6].toString());
			titulosSicoob.setDigContaCorrente(tupla[7].toString());			
			titulosSicoob.setNossoNumero(doc[0]);
			titulosSicoob.setNumeroDoDocumento(tupla[0].toString());
			titulosSicoob.setVencimento((Date) tupla[10]);
			titulosSicoob.setValor( valor );
			titulosSicoob.setEmissao((Date) tupla[13]);
			titulosSicoob.setCodCarteira(Integer.valueOf(tupla[8].toString()));
			try{
				titulosSicoob.setCodMora(1);
				titulosSicoob.setJurosDeMora(new BigDecimal(tupla[16].toString().replaceAll(",", ".")));
				titulosSicoob.setDataMora(DateUtil.somarDias((Date) tupla[10], 1));
			}catch(NullPointerException e){
				titulosSicoob.setCodMora(BigDecimal.ZERO.intValue());
				titulosSicoob.setDataMora(null);
				titulosSicoob.setJurosDeMora(BigDecimal.ZERO);
			}
			
			try{
				titulosSicoob.setCodigoDesconto(1);
				titulosSicoob.setDataDesconto((Date) tupla[10]);
				titulosSicoob.setDescontoConcedido(new BigDecimal(tupla[17].toString().replaceAll(",", ".")));
			}catch(NullPointerException e){
				titulosSicoob.setCodigoDesconto(BigDecimal.ZERO.intValue());
				titulosSicoob.setDataDesconto(null);
				titulosSicoob.setDescontoConcedido(BigDecimal.ZERO);
			}
			
			titulosSicoob.setIofDevido(BigDecimal.ZERO);
			try{
				titulosSicoob.setAbatimentoConcedido(new BigDecimal(tupla[18].toString().replaceAll(",", ".")));
			}catch(NullPointerException e){
				titulosSicoob.setAbatimentoConcedido(BigDecimal.ZERO);
			}
			titulosSicoob.setNossoNumeroEmp(tupla[0].toString());
			titulosSicoob.setCodigoProtesto(1);
			titulosSicoob.setDiasProtesto(1);
			titulosSicoob.setCodigoBaixa(2);
			titulosSicoob.setDiasBaixa(000);
			titulosSicoob.setNumeroContrato(Integer.parseInt(tupla[0].toString()));
			
			DetalheObrigatorioDadosPagadorSicoob pagadorSicoob = new DetalheObrigatorioDadosPagadorSicoob();
			pagadorSicoob.setNumeroSequencialRegistro( seqRegistro++ );
			pagadorSicoob.setTipoInscricaoSacado(Integer.parseInt(TipoInscricaoPagador.CNPJ.getId()));
			pagadorSicoob.setNomeSacado(tupla[21].toString());
			String cep = "";
			try{
				cep = StringUtils.right(ZERO_ESQUERDA + tupla[24].toString(), 8);
			}catch(Exception e){
				cep = ZERO_ESQUERDA;
			}
			int cepPrefix = Integer.parseInt(cep.substring(0, 5));
			int cepSufix = Integer.parseInt(cep.substring(5));
			pagadorSicoob.setCepSacado(cepPrefix);
			pagadorSicoob.setSufixoCep(cepSufix);
			pagadorSicoob.setCodBancoCorresp(0);
			pagadorSicoob.setNossoNumeroNoBancoCorresp("");
			
			try{
				pagadorSicoob.setNumeroInscricaoSacado(tupla[20].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("relatorioRemessaCNAB.exception.ValidacaoRemessaCNPJException", null, tupla[20]);
			}
			
			try{
				pagadorSicoob.setLogradouroSacado(tupla[22].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("relatorioRemessaCNAB.exception.ValidacaoRemessaLogradouroException", null, tupla[22]);
			}
			
			try{
				pagadorSicoob.setBairroSacado(tupla[23].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("relatorioRemessaCNAB.exception.ValidacaoRemessaBairroException", null, tupla[23]);
			}
			
			try{
				pagadorSicoob.setCidade(tupla[25].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("relatorioRemessaCNAB.exception.ValidacaoRemessaCidadeException", null, tupla[25]);
			}
			
			try{
				pagadorSicoob.setEstado(tupla[26].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("relatorioRemessaCNAB.exception.ValidacaoRemessaEstadoException", null, tupla[26]);
			}
			
			try{
				pagadorSicoob.setCveEstado(tupla[29].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("relatorioRemessaCNAB.exception.ValidacaoRemessaCVEEstadoException", null, tupla[29]);
			}
			
			titulosSicoob.setDetalheObrigatorioDadosPagadorSicoob(pagadorSicoob);
			
			arquivoRemessaItem.addTitulo(titulosSicoob);
			
		}
		
		if(arquivoRemessaItem != null){
			rodapeRemessaLoteSicoob = new RodapeRemessaLoteSicoob();
			rodapeRemessaLoteSicoob.setNumeroSequencialRegistro(qtdeTitulos);
			rodapeRemessaLoteSicoob.setValorRegistros( valorTitulos );
			
			rodapeRemessaSicoob = new RodapeRemessaSicoob();
			rodapeRemessaSicoob.setQtdLotes(1);
			rodapeRemessaSicoob.setQtdArquivos(qtdeTitulos);
			rodapeRemessaSicoob.setQtdContas(0);
			
			rodapeRemessaSicoob.setRodapeRemessaLoteSicoob(rodapeRemessaLoteSicoob);
			
			arquivoRemessaItem.setRodapeRemessa(rodapeRemessaSicoob);
		}
		
		nomeArquivo = nomeArquivo + new DecimalFormat("##").format(variavel) + ".REM";
		arquivoRemessa.setNomeArquivo(nomeArquivo);
		
		return arquivoRemessa;
	}
	
	@Override
	public ArquivoRemessa remessaCaixa(Empresa empresa, Date dataDe, Date dataAte, Boolean reenviar) throws Exception {
		
		StringBuilder sb = new StringBuilder();
		
		sb.append("SELECT ");
		sb.append("fb.FECHAMENTOBOLETO_ID AS \"id\", ");
		sb.append("(NVL(fp.COUNT_REMESSA, 0) + 1)  AS \"idRemessa\", ");
		sb.append("fp.COD_EMP_BANCO AS \"codEmpresaBanco\", ");
		sb.append("emp.CNPJ AS \"cnpj\", ");
		sb.append("emp.NOMBEMPRESA AS \"nomeEmpresa\", ");
		sb.append("fp.BOLETO_BANCO_AGENCIA AS \"agencia\", ");
		sb.append("fb.NOSSONUMERO AS \"nossoNumero\", ");
		sb.append("fb.FECVENCIMENTO AS \"vencimento\", ");
		sb.append("fb.VALORDOCUMENTO AS \"valor\", ");
		sb.append("fb.FECDOCUMENTO AS \"dataEmissao\", ");
		sb.append("(nvl(fb.porc_mora, 0)) AS \"porcMora\", ");
		sb.append("fb.DESCONTOS AS \"valorDesconto\", ");
		sb.append("fb.DEDUCOES AS \"valorAbatimento\", ");
		sb.append("'cnpj' as \"tipoInscricaoPagador\", ");
		sb.append("pv.NUMDOCPUNTOVENTA AS \"numeroInscricaoPagador\", ");
		sb.append("pv.NOMBPUNTOVENTA AS \"nomePagador\", ");
		sb.append("pv.DIRECCIONCALLE || ', ' || pv.DIRECCIONNUMERO AS \"logradouroPagador\", ");
		sb.append("pl.NOMBPLAZA AS \"bairroPagador\", ");
		sb.append("pv.CODPOSTAL AS \"cepPagador\", ");
		sb.append("ci.NOMBCIUDAD AS \"cidadePagador\", ");
		sb.append("es.NOMBESTADO AS \"estadoPagador\" ");
		writeFROMClause(sb, dataDe != null && dataAte != null, reenviar);
		
		Query query = getSession().createSQLQuery(sb.toString());
		query.setInteger(EMPRESA_ID, empresa.getEmpresaId());
		if(dataDe != null && dataAte != null){
			query.setDate(DATA_DE, dataDe);
			query.setDate(DATA_ATE, dataAte);
		}
		List<Object[]> list = query.list();
		
		ArquivoRemessa arquivoRemessa = new ArquivoRemessa(BancoLayout.CAIXA_400_Envio);
		
		String nomeArquivo = "CEF" + new SimpleDateFormat("ddMM").format(new Date());
		int variavel = 0;
		int seqRegistro = 0;
		int qtdeTitulos = 0;		
			
		ArquivoRemessaItem arquivoRemessaItem = null;
		CabecalhoRemessaCaixa cabecalhoRemessaCaixa = null;
		RodapeRemessaPadrao rodape = null;
		
		for(Object[] tupla : list){
			
			Integer idRemessa = Integer.valueOf(tupla[1].toString());
			variavel = idRemessa;
			String codEmpresaBanco = tupla[2] == null ? "" : ((BigDecimal) tupla[2]).toString();
			String versao = codEmpresaBanco.length() >6 ?"007":""; 
			codEmpresaBanco = StringUtils.right("0000000" + codEmpresaBanco, 7);			
			String nomeEmpresa = tupla[4].toString();
			BigDecimal valor = new BigDecimal(tupla[8].toString().replaceAll(",", "."));
			
			qtdeTitulos++;
			
			if(cabecalhoRemessaCaixa == null ){
				cabecalhoRemessaCaixa = new CabecalhoRemessaCaixa();
							
				cabecalhoRemessaCaixa.setAgenciaBeneficiario(tupla[5].toString());
				cabecalhoRemessaCaixa.setCodigoEmpresa(codEmpresaBanco);				
				cabecalhoRemessaCaixa.setNomeEmpresa(nomeEmpresa);
				cabecalhoRemessaCaixa.setDataGravacao(new Date());
				cabecalhoRemessaCaixa.setNumeroSequencialRemessa(idRemessa);
				cabecalhoRemessaCaixa.setVersaoLayout(versao);
				
				arquivoRemessaItem = new ArquivoRemessaCaixa();
				arquivoRemessaItem.setCabecalhoRemessa(cabecalhoRemessaCaixa);
				arquivoRemessa.addItem(arquivoRemessaItem);	
				
			}
			
			DetalheObrigatorioCaixa titulosCaixa = new DetalheObrigatorioCaixa();
			titulosCaixa.setIdBoletoFechamento(Integer.valueOf(tupla[0].toString()));
			
			titulosCaixa.setNumeroSequencialRegistro( seqRegistro++ );			
			titulosCaixa.setNossoNumero(tupla[6].toString());
			titulosCaixa.setNumeroDoDocumento(tupla[0].toString());
			titulosCaixa.setVencimento((Date) tupla[7]);
			titulosCaixa.setValor( valor );
			titulosCaixa.setEmissao((Date) tupla[9]);
			
			try{
				titulosCaixa.setValorAtraso( calculaValorMora( new BigDecimal(tupla[10].toString().replaceAll(",", ".") ), valor ));
			}catch(NullPointerException e){				
				titulosCaixa.setValorAtraso(BigDecimal.ZERO);
			}
			
			try{
				titulosCaixa.setDataLimiteDesconto((Date) tupla[7]);
				titulosCaixa.setValorDesconto(new BigDecimal(tupla[11].toString().replaceAll(",", ".")));
			}catch(NullPointerException e){				
				titulosCaixa.setDataLimiteDesconto((Date) tupla[7]);
				titulosCaixa.setValorDesconto(BigDecimal.ZERO);
			}
			
			titulosCaixa.setValorIOF(BigDecimal.ZERO);
			try{
				titulosCaixa.setValorAbatimentoConcedido(new BigDecimal(tupla[12].toString().replaceAll(",", ".")));
			}catch(NullPointerException e){
				titulosCaixa.setValorAbatimentoConcedido(BigDecimal.ZERO);
			}
			
			titulosCaixa.setNomeSacado(tupla[15].toString());			
			titulosCaixa.setTipoInscricaoPagador(TipoInscricaoPagador.CNPJ);
			
			try{
				titulosCaixa.setNumeroInscricao(tupla[3].toString().replaceAll(NUMERAIS, ""));
			}catch(Exception e){
				throw new ValidacaoRemessaException("O CNPJ do ponto de venda "+tupla[15]+" está fora do padrão, favor corrigir");
			}
			
			String cep = "";
			try{
				cep = StringUtils.right(ZERO_ESQUERDA + tupla[18].toString(), 8);
			}catch(Exception e){
				cep = ZERO_ESQUERDA;
			}

			titulosCaixa.setCepSacado(cep);
			
			try{
				titulosCaixa.setNumeroInscricaoSacado(tupla[14].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O CNPJ do ponto de venda "+tupla[15]+" está fora do padrão, favor corrigir");
			}
			
			try{
				titulosCaixa.setEnderecoSacado(tupla[16].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Logradouro do ponto de venda "+tupla[15]+" está fora do padrão, favor corrigir");
			}
			
			try{
				titulosCaixa.setBairroSacado(tupla[17].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Bairro do ponto de venda "+tupla[15]+" está fora do padrão, favor corrigir");
			}
			
			try{
				titulosCaixa.setCidade(tupla[19].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("A cidade do ponto de venda "+tupla[15]+" está fora do padrão, favor corrigir");
			}
			
			try{
				titulosCaixa.setEstado(tupla[20].toString());
			}catch(Exception e){
				throw new ValidacaoRemessaException("O Estado do ponto de venda "+tupla[15]+" está fora do padrão, favor corrigir");
			}
			
			titulosCaixa.setSacadorAvalista("");
			
			arquivoRemessaItem.addTitulo(titulosCaixa);
			
		}
		
		if(rodape == null){
			rodape = new RodapeRemessaPadrao();
			rodape.setNumeroSequencialRegistro(qtdeTitulos);
			arquivoRemessaItem.setRodapeRemessa(rodape);
		}
		
		nomeArquivo = nomeArquivo + new DecimalFormat("##").format(variavel) + ".REM";
		arquivoRemessa.setNomeArquivo(nomeArquivo);
		
		return arquivoRemessa;
	}
	
	private void writeFROMClause(StringBuilder sb, boolean hasDate, Boolean reenviar) {
		sb.append(" FROM ");
		sb.append(" FECHAMENTO_BOLETO fb ");
		sb.append(" INNER JOIN FECHAMENTO_CNTCORRENTE fc on fb.FECHAMENTOCNTCORRENTE_ID = fc.FECHAMENTOCNTCORRENTE_ID AND fc.ACTIVO = 1 ");
		sb.append(" INNER JOIN PUNTO_VENTA pv on pv.PUNTOVENTA_ID = fc.PUNTOVENTA_ID AND pv.ACTIVO = 1 "); 
		sb.append(" INNER JOIN EMPRESA emp on emp.EMPRESA_ID = fc.EMPRESA_ID AND emp.ACTIVO = 1 ");
		sb.append(" INNER JOIN FECHAMENTO_PARAMGERAL fp on fp.EMPRESA_ID = emp.EMPRESA_ID AND fp.ACTIVO = 1 ");
		sb.append(" INNER JOIN FECHAMENTO_PARAMPTOVTA fppv on fppv.EMPRESA_ID = emp.EMPRESA_ID AND fppv.ACTIVO = 1 and pv.PUNTOVENTA_ID = fppv.PUNTOVENTA_ID AND fppv.TIPOPAGAMENTO = 'B' ");
		sb.append(" LEFT JOIN INSTI_FINANCEIRA ifi ON ifi.CODIGO = fp.BOLETO_BANCO_COD ");
		sb.append(" LEFT JOIN PARADA pa on pa.PARADA_ID = pv.PARADA_ID AND pa.ACTIVO = 1 "); 
		sb.append(" LEFT JOIN CIUDAD ci on ci.CIUDAD_ID = pa.CIUDAD_ID AND ci.ACTIVO = 1 "); 
		sb.append(" LEFT JOIN PLAZA pl on pl.PLAZA_ID = ci.PLAZA_ID AND pl.ACTIVO = 1 "); 
		sb.append(" LEFT JOIN ESTADO es on es.ESTADO_ID = ci.ESTADO_ID AND es.ACTIVO = 1 "); 
		sb.append(" LEFT JOIN EMPRESA_CONTABANCARIA ecb ON emp.EMPRESA_ID = ecb.EMPRESA_ID AND ifi.INSTIFINANCEIRA_ID = ecb.INSTIFINANCEIRA_ID AND ecb.ACTIVO = 1 ");
		sb.append(" WHERE fb.activo = 1 "); 
		
		if(!reenviar){
			sb.append(" AND fb.REMESSA_ID IS NULL ");
		}
		
		sb.append(" AND fp.EMPRESA_ID = :empresaId ");
		
		if(hasDate){
			sb.append(" AND fb.FECDOCUMENTO BETWEEN :dataDe AND :dataAte ");
		}
		
		sb.append(" ORDER BY ");
		sb.append(" fb.FECMODIF, fb.FECDOCUMENTO ");
		
	}

	@Override
	public List<FechamentoBoleto> obtenerTodosParaRemessa(Empresa empresa, Date dataDe, Date dataAte, Boolean reenviar) {
		
		StringBuilder sb = new StringBuilder();
		sb.append(" SELECT ");
		sb.append(" fb.FECHAMENTOBOLETO_ID AS fechamentoboletoId, ");
		sb.append(" fb.nossonumero, ");
		sb.append(" fb.FECDOCUMENTO, ");
		sb.append(" fb.FECVENCIMENTO, ");
		sb.append(" fb.VALORDOCUMENTO, ");
		sb.append(" fb.STATUS, ");
		sb.append(" fb.REMESSA_ID as remessaId, ");
		sb.append(" fc.FECHAMENTOCNTCORRENTE_ID as fcId, ");
		sb.append(" emp.NOMBEMPRESA, ");
		sb.append(" pv.NOMBPUNTOVENTA, ");
		sb.append(" emp.EMPRESA_ID AS codEmpresaBanco, ");
		sb.append(" pv.PUNTOVENTA_ID ");
		
		writeFROMClause(sb, dataDe != null && dataAte != null, reenviar);
		
		Query query = getSession().createSQLQuery(sb.toString());
		query.setInteger(EMPRESA_ID, empresa.getEmpresaId());
		
		if(dataDe != null && dataAte != null){
			query.setDate(DATA_DE, dataDe);
			query.setDate(DATA_ATE, dataAte);
		}
		
		List<Object[]> list = query.list();
		List<FechamentoBoleto> retorno = new ArrayList<FechamentoBoleto>();
		
		for(Object[] tupla : list){
			FechamentoBoleto fb = new FechamentoBoleto();
			fb.setFechamentoboletoId( Long.valueOf(tupla[0].toString()));
			fb.setNossonumero( tupla[1].toString());
			fb.setFecdocumento( (Date)tupla[2]);
			fb.setFecvencimento( (Date)tupla[3]);
			fb.setValordocumento( (BigDecimal)tupla[4]);
			fb.setStatus( tupla[5].toString() );
			fb.setRemessaId( tupla[6]==null?null:Long.valueOf(tupla[6].toString()) );
			
			FechamentoCntcorrente fcc = new FechamentoCntcorrente();
			fcc.setFechamentocntcorrenteId( Long.valueOf(tupla[7].toString()));
			
			Integer codEmpresaBanco = tupla[10] != null ? Integer.valueOf(tupla[10].toString()) : 0;
			fcc.setEmpresa( new Empresa(codEmpresaBanco, tupla[8].toString()));
			
			Integer codPuntoVenta = tupla[11] != null ? Integer.valueOf(tupla[11].toString()) : 0;
			fcc.setPuntoventa( new PuntoVenta(codPuntoVenta, tupla[9].toString()));
			
			fb.setFechamentoCntcorrente(fcc);
			
			retorno.add(fb);
		}

		return retorno;
	}
	
	@Override
	public Boolean atualizaRemessa(Empresa empresa, ArquivoRemessa arquivoRemessa) throws Exception {
		
		if(arquivoRemessa == null || arquivoRemessa.getItens() == null) {
			return false;
		}
		
		String ids = "";
		int count = 0;
		int seqRemessa = 0;
		
		@SuppressWarnings("deprecation")
		Connection con = getSession().connection();
		Statement stmt = con.createStatement();
		con.setAutoCommit(false);
		
		for(ArquivoRemessaItemInteface ar : arquivoRemessa.getItens()){
			
			for(DetalheObrigatorio boleto : ar.getTitulos()){
				
				if(count == 50){
					ids = ids.substring(1);
					stmt.addBatch("UPDATE FECHAMENTO_BOLETO SET REMESSA_ID = " + seqRemessa + " WHERE FECHAMENTOBOLETO_ID IN ( " + ids + " )");
					count = 0;
					ids = "";
				}
				
				ids += "," + boleto.getIdBoletoFechamento();
				seqRemessa = ar.getCabecalhoRemessa().getNumeroSequencialRemessa();
			
				count++;
			}
		}
		
		if(count <= 50){
			ids = ids.substring(1);
			stmt.addBatch("UPDATE FECHAMENTO_BOLETO SET REMESSA_ID = " + seqRemessa + " WHERE FECHAMENTOBOLETO_ID IN ( " + ids + " )");
			count = 0;
			ids = "";
		}
		
		stmt.addBatch("UPDATE FECHAMENTO_PARAMGERAL SET COUNT_REMESSA = " + seqRemessa + " WHERE EMPRESA_ID = " + empresa.getEmpresaId());

		stmt.executeBatch();
		con.commit();
		stmt.close();
		
		
		
		return Boolean.TRUE;
	}
	
	public String buscarConstante(String nombre) {
		StringBuilder HQL = new StringBuilder();
		HQL.append(" select ");
		HQL.append(" 	valorconstante ");
		HQL.append(" from ");
		HQL.append(" 	Constante ");
		HQL.append(" where ");
		HQL.append(" 	nombconstante = :nombre ");
		HQL.append(" 	and activo = 1 ");
		Query query = getSession().createQuery(HQL.toString());
		query.setParameter("nombre", nombre);
		return (String) query.uniqueResult();
	}
	
	@Override
	public List<Empresa> getEmpresas() {
		
		Query query = getSession().createQuery("SELECT param.empresa FROM FechamentoParamgeral param WHERE param.activo = 1 AND param.empresa.activo = 1");
		
		return (List<Empresa>) query.list();
	}
	
	private String gerarCodigoTransmissao(String agencia, String agenciaDigito, String numeroConvenio, String numeroConta, String contaDigito) {
		
		StringBuilder sb = new StringBuilder();
		sb.append(StringUtils.leftPad(agencia, 4, '0'));
		sb.append(StringUtils.leftPad(numeroConvenio, 8, '0'));
		sb.append(StringUtils.leftPad(numeroConta.substring(0,numeroConta.length()-1), 8,'0')); // 2271 01152386 01300052
		
		
		return sb.toString();
	}
	
	private BigDecimal calculaValorMora( BigDecimal mora,  BigDecimal valor ) {
		if( mora != null  && mora.compareTo(BigDecimal.ZERO) > 0 ) {
			BigDecimal valorMora = (valor.multiply(mora)).divide( new BigDecimal("100"));
			return valorMora.setScale(2, RoundingMode.HALF_UP);
		}else {
			return BigDecimal.ZERO;
		}
	}

	@Override
	public FechamentoBoleto obtenerFechamentoBoletoPorNossoNumero(String nossoNumero, Integer empresaId) {
		StringBuilder sb = new StringBuilder();
		sb.append(" SELECT ");
		sb.append(" fb.FECHAMENTOBOLETO_ID AS fechamentoboletoId, ");
		sb.append(" fb.nossonumero, ");
		sb.append(" fb.FECDOCUMENTO, ");
		sb.append(" fb.FECVENCIMENTO, ");
		sb.append(" fb.VALORDOCUMENTO, ");
		sb.append(" fb.STATUS as status, ");
		sb.append(" fb.REMESSA_ID as remessaid, ");
		sb.append(" fb.indboletoquitado as indBoletoQuitado ");
		sb.append(" FROM ");
		sb.append(" FECHAMENTO_BOLETO fb ");
		sb.append(" INNER JOIN FECHAMENTO_CNTCORRENTE fc on fb.FECHAMENTOCNTCORRENTE_ID = fc.FECHAMENTOCNTCORRENTE_ID AND fc.ACTIVO = 1 ");
		sb.append(" WHERE fb.activo = 1 ");
		sb.append(" AND fb.nossonumero = :nossoNumero ");
		sb.append(" AND fc.EMPRESA_ID = :empresaId ");
		
		Query query = getSession().createSQLQuery(sb.toString())
				   .addScalar("fechamentoboletoId", LongType.INSTANCE)
				   .addScalar("nossonumero", StringType.INSTANCE)
				   .addScalar("status", StringType.INSTANCE)
				   .addScalar("remessaId", LongType.INSTANCE)
				   .addScalar("indBoletoQuitado", BooleanType.INSTANCE)				   
				   .setResultTransformer(new AliasToBeanResultTransformer(FechamentoBoleto.class));

		query.setString("nossoNumero", nossoNumero);
		query.setInteger(EMPRESA_ID, empresaId);

		FechamentoBoleto retorno = (FechamentoBoleto)query.uniqueResult();

		return retorno;
	}

	@Override
	public boolean quitarFechamentoBoleto(Long fechamentoboletoId, Integer usuarioId, DetalheRetorno detalhe) throws SQLException {

		@SuppressWarnings("deprecation")
		Connection con = getSession().connection();
		Statement stmt = con.createStatement();
		con.setAutoCommit(false);
		
		StringBuilder qry = new StringBuilder();
		qry.append(" update FECHAMENTO_BOLETO set INDBOLETOQUITADO = 1, ");
		qry.append(" FECMODIF = SYSDATE, ");
		qry.append(" USUARIO_ID_QUITA = ").append(usuarioId);		
		qry.append(" , FECBAIXA = TO_DATE('");
		qry.append( detalhe.getDataBaixa());
		qry.append("', 'DDMMYY')");
		
		if( detalhe.getValorJuros() != null) {
			qry.append(" , VALOR_JUROS = ").append(detalhe.getValorJuros());
		}else {
			qry.append(" , VALOR_JUROS = 0 ");
		}
		
		qry.append(" where FECHAMENTOBOLETO_ID = ").append(fechamentoboletoId);		
		qry.append(" AND ACTIVO = 1 ");

		
		int qtd = stmt.executeUpdate(qry.toString());
		con.commit();
		stmt.close();
		con.close();
		
		return qtd==1;
	}
	
	@Override
	public boolean quitarFechamentoBoleto(DetalheRetorno detalhe,Integer usuarioId) throws SQLException {

		@SuppressWarnings("deprecation")
		Connection con = getSession().connection();
		Statement stmt = con.createStatement();
		con.setAutoCommit(false);
		
		StringBuilder qry = new StringBuilder();
		qry.append(" update FECHAMENTO_BOLETO set INDBOLETOQUITADO = 1, ");
		qry.append(" FECMODIF = SYSDATE, ");
		qry.append(" USUARIO_ID_QUITA = ").append(usuarioId);		
		qry.append(" , FECBAIXA = TO_DATE('");
		qry.append( detalhe.getDataBaixa());
		qry.append("', 'DDMMYY')");
		
		if( detalhe.getValorJuros() != null) {
			qry.append(" , VALOR_JUROS = ").append(detalhe.getValorJuros());
		}else {
			qry.append(" , VALOR_JUROS = 0 ");
		}
		
		qry.append(" where FECHAMENTOBOLETO_ID = ").append(detalhe.getIdBoletoFechamento());		
		qry.append(" AND ACTIVO = 1 ");
		
		int qtd = stmt.executeUpdate(qry.toString());
		con.commit();
		stmt.close();
		con.close();
		
		return qtd==1;
	}
	
	private void zerarDesconto(DetalheObrigatorioDadosTitulosBancoBrasil titulo) {
		titulo.setCodigoDesconto(0);
		titulo.setDataDesconto(null);
		titulo.setDescontoConcedido(BigDecimal.ZERO);
	}

	@Override
	public FechamentoBoleto obtenerFechamentoBoletoPorId(Integer idBoletoFechamento) {
		StringBuilder sb = new StringBuilder();
		sb.append(" SELECT ");
		sb.append(" fb.FECHAMENTOBOLETO_ID AS fechamentoboletoId, ");
		sb.append(" fb.nossonumero, ");
		sb.append(" fb.FECDOCUMENTO, ");
		sb.append(" fb.FECVENCIMENTO, ");
		sb.append(" fb.VALORDOCUMENTO, ");
		sb.append(" fb.STATUS as status, ");
		sb.append(" fb.REMESSA_ID as remessaid, ");
		sb.append(" fb.indboletoquitado as indBoletoQuitado ");
		sb.append(" FROM ");
		sb.append(" FECHAMENTO_BOLETO fb ");
		sb.append(" INNER JOIN FECHAMENTO_CNTCORRENTE fc ");
		sb.append("   ON fb.FECHAMENTOCNTCORRENTE_ID = fc.FECHAMENTOCNTCORRENTE_ID ");
		sb.append("   AND fc.ACTIVO = 1 ");
		sb.append(" WHERE fb.activo = 1 ");
		sb.append(" AND fb.FECHAMENTOBOLETO_ID = :idFechamentoBoleto ");
		
		Query query = getSession().createSQLQuery(sb.toString())
				   .addScalar("fechamentoboletoId", LongType.INSTANCE)
				   .addScalar("nossonumero", StringType.INSTANCE)
				   .addScalar("status", StringType.INSTANCE)
				   .addScalar("remessaId", LongType.INSTANCE)
				   .addScalar("indBoletoQuitado", BooleanType.INSTANCE)				   
				   .setResultTransformer(new AliasToBeanResultTransformer(FechamentoBoleto.class));

		query.setInteger("idFechamentoBoleto", idBoletoFechamento);

		FechamentoBoleto retorno = (FechamentoBoleto)query.uniqueResult();

		return retorno;
	}
	
}
