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.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.hibernate.Query; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import com.rjconsultores.ventaboletos.constantes.Constantes; import com.rjconsultores.ventaboletos.dao.CalcularPeajeDAO; import com.rjconsultores.ventaboletos.entidad.CasetaPeaje; import com.rjconsultores.ventaboletos.entidad.CasetaPeajeExcepcion; import com.rjconsultores.ventaboletos.entidad.ClaseServicio; import com.rjconsultores.ventaboletos.entidad.ClasseIndicePeaje; import com.rjconsultores.ventaboletos.entidad.ExcepcionPeaje; import com.rjconsultores.ventaboletos.entidad.ExcepcionPeajeVigencia; import com.rjconsultores.ventaboletos.entidad.OrgaoConcedente; import com.rjconsultores.ventaboletos.entidad.Parada; import com.rjconsultores.ventaboletos.entidad.Ruta; import com.rjconsultores.ventaboletos.service.OrgaoConcedenteService; import com.rjconsultores.ventaboletos.utilerias.ApplicationProperties; import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado; @Repository("calcularPeajeDAO") public class CalcularPeajeHibernateDAO extends GenericHibernateDAO implements CalcularPeajeDAO { @Autowired private OrgaoConcedenteService orgaoConcedenteService; @Autowired public CalcularPeajeHibernateDAO(@Qualifier("sessionFactory") SessionFactory factory) { setSessionFactory(factory); } @Override public List buscarRutaWithCasetaPeajeFromOrgao(OrgaoConcedente oc) { StringBuilder sql = new StringBuilder() .append("select distinct r ") .append("from Ruta r, RutaCaseta rc, RutaSecuencia rs, CasetaPeaje cp ") .append("where rc.rutaSecuencia.rutasecuenciaId = rs.rutasecuenciaId ") .append(" and rc.casetaPeaje.casetaPeajeId = cp.casetaPeajeId ") .append(" and rs.ruta.rutaId = r.rutaId "); if (oc != null && oc.getOrgaoConcedenteId() != null) { sql.append(" and r.orgaoConcedente.orgaoConcedenteId = :orgaoConcedenteId "); } sql.append(" order by r.descruta "); Query query = getSession().createQuery(sql.toString()); if (oc != null && oc.getOrgaoConcedenteId() != null) { query.setInteger("orgaoConcedenteId", oc.getOrgaoConcedenteId()); } return query.list(); } @Override public List buscarCasetasPeajeWithinTramo(Ruta ruta) { StringBuilder sql = new StringBuilder() .append("with tramo_tmp as ( ") .append(" select t.origen_id as orig, t.destino_id as dest, t.tramo_id as tra, ") .append(" t.desctramo as tradesc, t.origen_id as traorig, t.destino_id as tradest, ") .append(" t.via_id as travia, t.cantkmreal as tracantkm, t.cantkmpagoconductor as tracantkmpago, ") .append(" t.activo as traactivo, t.fecmodif as trafecmodif, t.usuario_id as trausuario ") .append(" from ruta_combinacion rcom ") .append(" inner join ruta r on r.ruta_id = rcom.ruta_id ") .append(" inner join orgao_concedente oc on oc.orgaoconcedente_id = r.orgaoconcedente_id ") .append(" inner join tramo t on t.tramo_id = rcom.tramo_id ") .append(" where r.ruta_id = :rutaId ") .append("), mytable as ( ") .append(" select eiorig.icms as icms, ") .append(" rseqorig.numsecuencia as origen_tramo_inicial_seq, rseqdest.numsecuencia as destino_tramo_final_seq, ") .append(" torig.tramo_id as tramo_orig, tdest.tramo_id as tramo_dest, ") .append(" tt.tra as tracomb, tt.orig as ttorig, tt.dest as ttdest, ") .append(" tt.tradesc as tracombdesc, tt.traorig as tracomborig, tt.tradest as tracombdest, ") .append(" tt.travia as tracombvia, tt.tracantkm as tracombcantkm, tt.tracantkmpago as tracombcantkmpago, ") .append(" tt.traactivo as tracombactivo, tt.trafecmodif as tracombfecmodif, tt.trausuario as tracombusuario ") .append(" from ruta_secuencia rseqorig ") .append(" inner join tramo torig on torig.tramo_id = rseqorig.tramo_id and rseqorig.ruta_id = :rutaId ") .append(" inner join ruta_secuencia rseqdest on rseqorig.ruta_id = rseqdest.ruta_id ") .append(" inner join tramo tdest on tdest.tramo_id = rseqdest.tramo_id and rseqdest.ruta_id = :rutaId ") .append(" inner join ruta_empresa re on re.ruta_id = :rutaId ") .append(" inner join empresa e on re.empresa_id = e.empresa_id ") .append(" inner join parada porig on torig.origen_id = porig.parada_id ") .append(" inner join ciudad corig on corig.ciudad_id = porig.ciudad_id ") .append(" inner join estado eorig on eorig.estado_id = corig.estado_id ") .append(" inner join empresa_imposto eiorig on eiorig.empresa_id = e.empresa_id and eiorig.estado_id = eorig.estado_id ") .append(" inner join tramo_tmp tt on torig.origen_id = tt.orig and tdest.destino_id = tt.dest ") .append("), caseta_tramo_da_ruta as ( ") .append(" select rcas.rutacaseta_id as rutacasetaid, rcas.rutasecuencia_id as rutasecuenciaid, rcas.casetapeaje_id, ") .append(" rseq1.numsecuencia as numsecuencia, rseq1.tramo_id as tramoid, rseq2.numsecuencia as numsecuencia2, ") .append(" casp.casetapeaje_id as casetapeajeid, casp.desccaseta as desccaseta, casp.importeida as importeida, ") .append(" casp.importevuelta as importevuelta, casp.activo as caspactivo, casp.fecmodif as caspfecmodif, ") .append(" casp.usuario_id as caspusuario ") .append(" from ruta_caseta rcas ") .append(" inner join ruta_secuencia rseq1 on rcas.rutasecuencia_id = rseq1.rutasecuencia_id ") .append(" inner join ruta_secuencia rseq2 on rseq2.tramo_id = rseq1.tramo_id ") .append(" inner join tramo tra on tra.tramo_id = rseq1.tramo_id and rseq1.ruta_id = :rutaId ") .append(" inner join caseta_peaje casp on casp.casetapeaje_id = rcas.casetapeaje_id ") .append(") ") .append("select distinct origen_tramo_inicial_seq, destino_tramo_final_seq, tramo_orig, tramo_dest, tracomb, ttorig, ttdest, ") .append(" tracombdesc, tracomborig, tracombdest, tracombvia, tracombcantkm, tracombcantkmpago, tracombactivo, ") .append(" tracombfecmodif, tracombusuario, rutacasetaid, rutasecuenciaid, casetapeaje_id, tramoid, casetapeajeid, ") .append(" desccaseta, importeida, importevuelta, caspactivo, caspfecmodif, caspusuario, icms ") .append("from mytable my ") .append(" inner join caseta_tramo_da_ruta ctr on ctr.numsecuencia between my.origen_tramo_inicial_seq and my.destino_tramo_final_seq ") .append(" order by tracomb "); Query query = getSession().createSQLQuery(sql.toString()); query.setInteger("rutaId", ruta.getRutaId()); query.setInteger("rutaId", ruta.getRutaId()); query.setInteger("rutaId", ruta.getRutaId()); query.setInteger("rutaId", ruta.getRutaId()); return query.list(); } // pra cada ruta obter as combinacoes de tramos, cada tramo com sua lista de casetaPeaje public int[] gerarSQLInserirPeajes(List lsRuta, OrgaoConcedente orgao, boolean usaICMS) { List peajes = new ArrayList(); orgao = orgaoConcedenteService.obtenerID(orgao.getOrgaoConcedenteId()); List classeIndicePeajes = orgao.getClassesIndicePeaje(); for (Ruta ruta : lsRuta) { List lsObj = buscarCasetasPeajeWithinTramo(ruta); if (null != lsObj) { for (Object arrObj : lsObj) { peajes.add(PeajeVO.create(ruta, orgao, (Object[]) arrObj, classeIndicePeajes, usaICMS)); } } } StringBuilder updateSql = new StringBuilder() .append("update peaje set activo = 0 ") .append("where orgaoconcedente_id = ") .append(orgao.getOrgaoConcedenteId()); int[] result = {}; Connection con = getSession().connection(); try { Statement stmt = con.createStatement(); con.setAutoCommit(false); stmt.addBatch(updateSql.toString()); for (PeajeVO pvo : peajes) { stmt.addBatch(pvo.toInsertQuery()); stmt.addBatch(pvo.toUpdateExcepcionPeajeQuery()); stmt.addBatch(pvo.toUpdateExcepcionPeajeVigenciaQuery()); } result = stmt.executeBatch(); con.commit(); recalcularExcecoesPedagio(peajes); } catch (SQLException e) { e.printStackTrace(); } return result; } private Map buscaCasetas(List pvo) { Set ids = new LinkedHashSet(); Map casetas = new HashMap(); for (PeajeVO p : pvo) { ids.add(p.casetaPeajeId); } if(!ids.isEmpty()){ Query query = getSession() .createQuery("select c from CasetaPeaje c where c.casetaPeajeId in (:ids) "); query.setParameterList("ids", ids); for (CasetaPeaje c : (List) query.list()) { casetas.put(c.getCasetaPeajeId(), c); } } return casetas; } private ExcepcionPeaje getExcepcion(Integer rutaId, Integer origenId, Integer destinoId) { Query query = getSession().createQuery("select e from ExcepcionPeaje e where e.ruta.rutaId = :rutaId " + "and e.origem.paradaId = :origenId and e.destino.paradaId = :destinoId and e.activo = 1 "); query.setInteger("rutaId", rutaId); query.setInteger("origenId", origenId); query.setInteger("destinoId", destinoId); return (ExcepcionPeaje) query.uniqueResult(); } private Parada getParada(Integer paradaId) { return (Parada) getSession().get(Parada.class, paradaId); } private Ruta getRuta(Integer rutaId) { return (Ruta) getSession().get(Ruta.class, rutaId); } @Transactional private void recalcularExcecoesPedagio(List pvos) { Map casetas = buscaCasetas(pvos); for (PeajeVO peaje : pvos) { ExcepcionPeaje excepcion = null; CasetaPeaje caseta = casetas.get(peaje.casetaPeajeId); for (CasetaPeajeExcepcion cpe : caseta.getLsCasetaPeajeExcepcion()) { if (excepcion == null) { excepcion = new ExcepcionPeaje(); excepcion.setActivo(true); excepcion.setDestino(getParada(peaje.destinoId)); excepcion.setFecmodif(Calendar.getInstance().getTime()); excepcion.setOrigem(getParada(peaje.origenId)); excepcion.setRuta(getRuta(peaje.rutaId)); excepcion.setUsuarioId(1); } ExcepcionPeajeVigencia epv = new ExcepcionPeajeVigencia(); epv.setActivo(cpe.getActivo()); epv.setExcepcionPeaje(excepcion); epv.setFecmodif(Calendar.getInstance().getTime()); epv.setFecVentaFin(cpe.getFecVentaFin()); epv.setFecVentaIni(cpe.getFecVentaIni()); epv.setHoraFin(cpe.getHoraFin()); epv.setHoraIni(cpe.getHoraIni()); epv.setINDDOMINGO(cpe.getINDDOMINGO()); epv.setINDJUEVES(cpe.getINDJUEVES()); epv.setINDLUNES(cpe.getINDLUNES()); epv.setINDMARTES(cpe.getINDMARTES()); epv.setINDMIERCOLES(cpe.getINDMIERCOLES()); epv.setINDSABADO(cpe.getINDSABADO()); epv.setINDVIERNES(cpe.getINDVIERNES()); epv.setPrecio(cpe.getPrecio()); epv.setUsuarioId(1); epv.setCasetaPeaje(caseta); excepcion.getLsExcepcionPeajeVigencia().add(epv); } if (excepcion != null) { getSession().saveOrUpdate(excepcion); } } } private static class PeajeVO { private static final int HIGH_PRECISION = 10; private static final BigDecimal A_HUNDRED = new BigDecimal(100); private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); private Integer rutaId; private Integer origenId; private Integer destinoId; private Integer orgaoId; private Integer casetaPeajeId; private Integer cantAsientos; private Integer cantEixos; private BigDecimal importePeaje; private BigDecimal indicePeaje; private Integer activo; private Date fecmodif; private Integer usuarioId; private static BigDecimal getCantEixos(Ruta ruta) { try { return new BigDecimal(ruta.getCantEixos()); } catch (NullPointerException e) { throw new RuntimeException("rutaSemQtdEixos;" + ruta.getRutaId()); } } private static BigDecimal getRutaCantAsientos(Ruta ruta) { try { return new BigDecimal(ruta.getCantAsientos()); } catch (NullPointerException e) { throw new RuntimeException("rutaSemQtdAsientos;" + ruta.getRutaId()); } } private static BigDecimal getImporte(Ruta ruta, Object[] obj) { if (ruta.getIndSentidoIda()) { return new BigDecimal(obj[22].toString()); } else { return new BigDecimal(obj[23].toString()); } } private static BigDecimal getIcms(Ruta ruta, Object[] obj) { return new BigDecimal(obj[27].toString()) .divide(A_HUNDRED, HIGH_PRECISION, RoundingMode.HALF_UP); } // ((importe * rutaCantEixos) / (indice * rutaCantAsientos)) / ( 1 - icms) private static BigDecimal calculateImportePeajeANTT(BigDecimal importe, BigDecimal icms, BigDecimal indice, BigDecimal rutaCantEixos, BigDecimal rutaCantAsientos, boolean usaICMS) { if (ApplicationProperties.getInstance().calculoPeajeReunidasANTT()) { // (importe * rutaCantEixos) / (indice) return importe.multiply(rutaCantEixos) .divide(indice, HIGH_PRECISION, RoundingMode.HALF_UP); } else { if(!usaICMS){ return importe.multiply(rutaCantEixos) .divide(indice.multiply(rutaCantAsientos), HIGH_PRECISION, RoundingMode.HALF_UP); }else{ return importe.multiply(rutaCantEixos) .divide(indice.multiply(rutaCantAsientos), HIGH_PRECISION, RoundingMode.HALF_UP) .divide(BigDecimal.ONE.subtract(icms), HIGH_PRECISION, RoundingMode.HALF_UP); } } } // ((importe * rutaCantEixos) / (indice)) / ( 1 - icms) private static BigDecimal calculateImportePeajeARTESP(BigDecimal importe, BigDecimal icms, BigDecimal indice, BigDecimal rutaCantEixos, boolean usaICMS) { if(!usaICMS){ return importe.multiply(rutaCantEixos) .divide(indice, HIGH_PRECISION, RoundingMode.HALF_UP); }else{ return importe.multiply(rutaCantEixos) .divide(indice, HIGH_PRECISION, RoundingMode.HALF_UP) .divide(BigDecimal.ONE.subtract(icms), HIGH_PRECISION, RoundingMode.HALF_UP); } } private static BigDecimal calculateImportePeaje(Ruta ruta, OrgaoConcedente orgao, Object[] obj, BigDecimal indicePeaje, boolean usaICMS) { BigDecimal rutaCantEixos = getCantEixos(ruta); BigDecimal indice = indicePeaje; BigDecimal importe = getImporte(ruta, obj); BigDecimal icms = usaICMS ? getIcms(ruta, obj) : null; if (Constantes.ORGAOS_CONCEDENTES_CALCULO_ARTESP.contains(orgao.getOrgaoConcedenteId())) { return calculateImportePeajeARTESP(importe, icms, indice, rutaCantEixos, usaICMS); } if (Constantes.ORGAOS_CONCEDENTES_CALCULO_ANTT.contains(orgao.getOrgaoConcedenteId()) || orgao.getDescOrgao().equals("AGEPAN")) { return calculateImportePeajeANTT(importe, icms, indice, rutaCantEixos, getRutaCantAsientos(ruta), usaICMS); } return BigDecimal.ZERO; // TODO throw an exception? como calcular quando é outro orgao concendente? } private static BigDecimal getIndicePeaje(ClaseServicio claseServicio, OrgaoConcedente orgao, List lsClasseIndicePeaje) { for (ClasseIndicePeaje classeIndicePeaje : lsClasseIndicePeaje) { if (claseServicio.equals(classeIndicePeaje.getClasseServicio())) { return classeIndicePeaje.getIndicePeaje(); } } return orgao.getIndicePeaje(); } private static PeajeVO create(Ruta ruta, OrgaoConcedente orgao, Object[] obj, List lsClasseIndicePeaje, boolean usaICMS) { PeajeVO pvo = new PeajeVO(); pvo.rutaId = ruta.getRutaId(); pvo.cantEixos = ruta.getCantEixos(); pvo.cantAsientos = ruta.getCantAsientos(); pvo.origenId = Integer.parseInt(obj[8].toString()); pvo.destinoId = Integer.parseInt(obj[9].toString()); pvo.orgaoId = orgao.getOrgaoConcedenteId(); pvo.casetaPeajeId = Integer.parseInt(obj[20].toString()); pvo.indicePeaje = getIndicePeaje(ruta.getClaseServicio(), orgao, lsClasseIndicePeaje); pvo.importePeaje = calculateImportePeaje(ruta, orgao, obj, pvo.indicePeaje, usaICMS); pvo.activo = 1; pvo.fecmodif = new Date(); pvo.usuarioId = UsuarioLogado.getUsuarioLogado().getUsuarioId(); return pvo; } private String toInsertQuery() { return new StringBuilder() .append("insert into peaje ( peaje_id, ruta_id, origen_id, destino_id, ") .append(" orgaoconcedente_id, casetapeaje_id, cantasientos, canteixos, ") .append(" importepeaje, indicepeaje, activo, fecmodif, usuario_id ) ") .append("values ( peaje_seq.nextval, ") .append(rutaId).append(", ") .append(origenId).append(", ") .append(destinoId).append(", ") .append(orgaoId).append(", ") .append(casetaPeajeId).append(", ") .append(cantAsientos).append(", ") .append(cantEixos).append(", ") .append(importePeaje).append(", ") .append(indicePeaje).append(", ") .append(activo).append(", ") .append("to_date('") .append(SDF.format(fecmodif)) .append("', 'yyyy/mm/dd hh24:mi:ss'), ") .append(usuarioId).append(" ) ") .toString(); } private String toUpdateExcepcionPeajeQuery() { return new StringBuilder() .append("update excepcion_peaje ") .append("set activo = 0 ") .append("where ruta_id = ").append(rutaId) .append(" and origen_id = ").append(origenId) .append(" and destino_id = ").append(origenId) .toString(); } private String toUpdateExcepcionPeajeVigenciaQuery() { return new StringBuilder() .append("update excepcion_peaje_vigencia ") .append("set activo = 0 ") .append("where excepcionpeaje_id in ( ") .append(" select excepcionpeaje_id ") .append(" from excepcion_peaje ") .append(" where ruta_id = ").append(rutaId) .append(" and origen_id = ").append(origenId) .append(" and destino_id = ").append(origenId) .append(")") .toString(); } } }