package com.rjconsultores.ventaboletos.service.impl; import java.math.BigDecimal; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.rjconsultores.ventaboletos.constantes.Constantes; import com.rjconsultores.ventaboletos.dao.ComissaoDAO; import com.rjconsultores.ventaboletos.entidad.Comissao; import com.rjconsultores.ventaboletos.entidad.DescontoComissao; import com.rjconsultores.ventaboletos.entidad.PtovtaComissao; import com.rjconsultores.ventaboletos.entidad.PtovtaComissao.Receita; import com.rjconsultores.ventaboletos.enums.IndStatusBoleto; import com.rjconsultores.ventaboletos.exception.ComissaoException; import com.rjconsultores.ventaboletos.service.CalculoComissaoService; import com.rjconsultores.ventaboletos.service.ComissaoService; import com.rjconsultores.ventaboletos.service.DescontoComissaoService; import com.rjconsultores.ventaboletos.service.PtovtaComissaoService; import com.rjconsultores.ventaboletos.utilerias.DateUtil; import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado; import com.rjconsultores.ventaboletos.vo.comissao.BoletoComissao; import com.rjconsultores.ventaboletos.vo.comissao.ComissaoDesconto; import com.rjconsultores.ventaboletos.vo.comissao.ComissaoDesconto.TipoDesconto; import com.rjconsultores.ventaboletos.vo.comissao.ComissaoReceita; import com.rjconsultores.ventaboletos.vo.comissao.RegistroCalculo; @Service("calculoComissaoService") public class CalculoComissaoServiceImpl implements CalculoComissaoService { private static final Logger log = LoggerFactory.getLogger(CalculoComissaoServiceImpl.class); private static final BigDecimal CEM = BigDecimal.TEN.multiply(BigDecimal.TEN); @Autowired private PtovtaComissaoService ptovtaComissaoService; @Autowired private ComissaoService comissaoService; @Autowired private ComissaoDAO comissaoDAO; @Autowired private DescontoComissaoService descontoComissaoService; public boolean validaCompetencia(Date periodo) { Calendar calendario = Calendar.getInstance(); calendario.setTime(periodo); int mes = calendario.get(Calendar.MONTH) + 1; int ano = calendario.get(Calendar.YEAR); Calendar now = Calendar.getInstance(); int mesNow = now.get(Calendar.MONTH) + 1; int anoNow = now.get(Calendar.YEAR); if (anoNow == ano) { if (mesNow > mes) { return true; } } else if (anoNow > ano) { return true; } return false; } @Override public void registrarCalculoComissao(Integer puntoVentaId, Integer empresaId, Date periodo) throws ComissaoException { if (validaCompetencia(periodo)) { String competencia = DateUtil.getStringDate(periodo, "MM/yyyy"); List comissoes = comissaoDAO.buscaComissaoVigencia(puntoVentaId, empresaId, competencia); if (comissoes.isEmpty()) { RegistroCalculo rc = realizarCalculoComissao(puntoVentaId, empresaId, periodo); Comissao comissao = new Comissao(); comissao.setCompetencia(competencia); comissao.setDataPagamento(Calendar.getInstance().getTime()); comissao.setEmpresaId(empresaId); comissao.setPuntoVentaId(puntoVentaId); comissao.setBonificacaoMetas(rc.getComissaoBonificaoMetas()); comissao.setComissaoBpr(rc.getComissaoBPR()); comissao.setEntregasPassagem(rc.getComissaoEntregaPassagem()); comissao.setReceitaExcessobagagem(rc.getComissaoExcessoBagagem()); comissao.setReceitaSeguroopcional(rc.getComissaoSegOpcional()); comissao.setReceitaOutros(rc.getComissaoOutros()); comissao.setRoyaties(rc.getRoyaties()); comissao.setIssRetido(rc.getRetidoISS()); comissao.setBonificacaoMetas(rc.getComissaoBonificaoMetas()); comissao.setDescontosEventuais(rc.getDescontos()); comissao.setIndPago(true); comissao.setUsuarioPagamentoId(UsuarioLogado.getUsuarioLogado().getUsuarioId()); comissao = comissaoService.suscribir(comissao); } else { throw new ComissaoException("busquedaCalculoComissaoController.registro.exception"); } } else { throw new ComissaoException("busquedaCalculoComissaoController.competencia.exception"); } } @Override public RegistroCalculo relatorioCalculoComissao(Integer puntoVentaId, Integer empresaId, Date periodo) { return realizarCalculoComissao(puntoVentaId, empresaId, periodo); } private BigDecimal calculoComisssaoBPR(boolean isAltaTemporada, PtovtaComissao ptovtaComissao, ComissaoReceita cr) { // Comissão BPR = Receita Comissão * (% Com BPR) BigDecimal bpr = BigDecimal.ZERO; BigDecimal receitaBPR = cr.getReceitaBPR().add(cr.getReceitaGAP()); if (isAltaTemporada) { bpr = receitaBPR.multiply(ptovtaComissao.getPassagemAlta().divide(CEM)); } else { bpr = receitaBPR.multiply(ptovtaComissao.getPassagemBaixa().divide(CEM)); } return bpr; } private BigDecimal calculoEntregaPassagem(boolean isAltaTemporada, PtovtaComissao ptovtaComissao, ComissaoReceita cr) { // EntregaPassagem (Internet/Venda Impressão Posterior/Outros) BigDecimal entregaPassagem = BigDecimal.ZERO; BigDecimal receitaEntrega = cr.getGapImpressa().add(cr.getInternet()); if (ptovtaComissao.getIndimpressaogapporc()) { entregaPassagem = receitaEntrega.multiply(ptovtaComissao.getValorImpressaoGap().divide(CEM)); } else { entregaPassagem = ptovtaComissao.getValorImpressaoGap().multiply(new BigDecimal(cr.getContImpressa())); } return entregaPassagem; } private BigDecimal calculoExcessoBagagem(boolean isAltaTemporada, PtovtaComissao ptovtaComissao, ComissaoReceita cr) { // Comissão Excesso = Receita Excesso Bagagem * (% Com. Exc. Bag) BigDecimal excessoBagagem = BigDecimal.ZERO; if (isAltaTemporada) { excessoBagagem = cr.getReceitaExcessoBagagem().multiply(ptovtaComissao.getExcessoAlta().divide(CEM)); } else { excessoBagagem = cr.getReceitaExcessoBagagem().multiply(ptovtaComissao.getExcessoBaixa().divide(CEM)); } return excessoBagagem; } private BigDecimal calculoSeguroOpcional(boolean isAltaTemporada, PtovtaComissao ptovtaComissao, ComissaoReceita cr) { // Comissão Seg. Opcional = Receita Seguro Opcional * (% Com. Seg. Pol) BigDecimal segOpcional = BigDecimal.ZERO; if (isAltaTemporada) { segOpcional = cr.getReceitaSeguroOpcional().multiply(ptovtaComissao.getSeguroAlta().divide(CEM)); } else { segOpcional = cr.getReceitaSeguroOpcional().multiply(ptovtaComissao.getSeguroBaixa().divide(CEM)); } return segOpcional; } private BigDecimal calculoOutros(boolean isAltaTemporada, PtovtaComissao ptovtaComissao, ComissaoReceita cr) { // Comissão Seg. Opcional = Receita Seguro Opcional * (% Com. Seg. Pol) BigDecimal outros = BigDecimal.ZERO; if (isAltaTemporada) { outros = cr.getReceitaSeguroOutros().multiply(ptovtaComissao.getOutrosAlta().divide(CEM)); } else { outros = cr.getReceitaSeguroOutros().multiply(ptovtaComissao.getOutrosBaixa().divide(CEM)); } return outros; } private Map calculoDescontos(Integer puntoVentaId, Integer empresaId, Date periodo, PtovtaComissao ptovtaComissao) { List lsDescontos = new ArrayList(); BigDecimal valorDescontoTotal = BigDecimal.ZERO; Date inicioPeriodo = DateUtil.inicioFechaPeriodoMeses(periodo); Date fimPeriodo = DateUtil.fimFechaPeriodoMeses(periodo); List itensDescontos = descontoComissaoService.buscaDescontoComissaoPeriodo(puntoVentaId, empresaId, inicioPeriodo, fimPeriodo); for (DescontoComissao dc : itensDescontos) { BigDecimal valorDesconto = dc.getPreco(); valorDescontoTotal = valorDescontoTotal.add(valorDesconto); ComissaoDesconto desconto = new ComissaoDesconto(); if (dc.getDatafinal() == null) { desconto.setTipo(TipoDesconto.FIXO); } else { desconto.setTipo(TipoDesconto.EVENTUAL); } desconto.setNomeDesconto(dc.getItemDesconto().getNomitemdesconto()); desconto.setValorDesconto(valorDesconto); lsDescontos.add(desconto); } Map respDescontos = new HashMap(); respDescontos.put("LISTA_DESCONTOS", lsDescontos); respDescontos.put("VALOR_DESCONTOS", valorDescontoTotal); return respDescontos; } @SuppressWarnings("unchecked") public RegistroCalculo realizarCalculoComissao(Integer puntoVentaId, Integer empresaId, Date periodo) { PtovtaComissao ptovtaComissao = ptovtaComissaoService.buscarPuntaVentaEmpresa(puntoVentaId, empresaId); List receitasBoleto = comissaoDAO.buscarReceitasComissoes(puntoVentaId, empresaId, periodo); Calendar calendario = Calendar.getInstance(); calendario.setTime(periodo); int ultimodia = calendario.getActualMaximum(Calendar.DAY_OF_MONTH); int mes = calendario.get(Calendar.MONTH) + 1; int ano = calendario.get(Calendar.YEAR); List receitas = calculaReceitaComissao(ptovtaComissao, receitasBoleto, ultimodia, mes, ano); RegistroCalculo rc = new RegistroCalculo(); BigDecimal comissaoBPR = BigDecimal.ZERO; BigDecimal comissaoExcessoBagagem = BigDecimal.ZERO; BigDecimal comissaoSegOpcional = BigDecimal.ZERO; BigDecimal comissaoEntregaPassagem = BigDecimal.ZERO; BigDecimal comissaoOutros = BigDecimal.ZERO; BigDecimal receitaTotal = BigDecimal.ZERO; for (ComissaoReceita cr : receitas) { // Está parte esta encapsulada, posteriormente será implementada a validação de alta e baixa temporada // Inicialmente só será validado os calculos de comissão em baixa temporada boolean isAltaTemporada = false; receitaTotal = receitaTotal.add(cr.getReceitaComissao()); BigDecimal bpr = calculoComisssaoBPR(isAltaTemporada, ptovtaComissao, cr); cr.setComissaoBPRDiaria(bpr); comissaoBPR = comissaoBPR.add(bpr); BigDecimal entregaPassagem = calculoEntregaPassagem(isAltaTemporada, ptovtaComissao, cr); cr.setComissaoEntregaPassagemDiaria(entregaPassagem); comissaoEntregaPassagem = comissaoEntregaPassagem.add(entregaPassagem); BigDecimal excessoBagagem = calculoExcessoBagagem(isAltaTemporada, ptovtaComissao, cr); cr.setComissaoExcessoBagagemDiaria(excessoBagagem); comissaoExcessoBagagem = comissaoExcessoBagagem.add(excessoBagagem); BigDecimal segOpcional = calculoSeguroOpcional(isAltaTemporada, ptovtaComissao, cr); cr.setComissaoSegOpcionalDiaria(segOpcional); comissaoSegOpcional = comissaoSegOpcional.add(segOpcional); BigDecimal outros = calculoOutros(isAltaTemporada, ptovtaComissao, cr); cr.setComissaoOutrosDiaria(outros); comissaoOutros = comissaoOutros.add(outros); } rc.setLsReceitas(receitas); rc.setComissaoBPR(comissaoBPR); rc.setComissaoExcessoBagagem(comissaoExcessoBagagem); rc.setComissaoSegOpcional(comissaoSegOpcional); rc.setComissaoEntregaPassagem(comissaoEntregaPassagem); rc.setComissaoOutros(comissaoOutros); // Descontos (Fixos e Eventuais) Map respDescontos = calculoDescontos(puntoVentaId, empresaId, periodo, ptovtaComissao); rc.setDescontos((BigDecimal) respDescontos.get("VALOR_DESCONTOS")); rc.setLsDescontos((List) respDescontos.get("LISTA_DESCONTOS")); // Bonificação Metas BigDecimal comissaoBonificaoMetas = BigDecimal.ZERO; rc.setComissaoBonificaoMetas(comissaoBonificaoMetas); // Royaties BigDecimal royaties = BigDecimal.ZERO; royaties = receitaTotal.multiply(ptovtaComissao.getRoyalties().divide(CEM)); rc.setRoyaties(royaties); // ISS retido BigDecimal issRetido = BigDecimal.ZERO; issRetido = receitaTotal.multiply(ptovtaComissao.getIssretido().divide(CEM)); rc.setRetidoISS(issRetido); // Comissão à pagar = Comissão BPR + Comissão Excesso Bagagem + Comissão Seg. Opcional + Bonificação Metas + Internet(EntregaPassagem) BigDecimal comissaoPagar = BigDecimal.ZERO; comissaoPagar = comissaoPagar.add(comissaoBPR).add(comissaoExcessoBagagem).add(comissaoSegOpcional); comissaoPagar = comissaoPagar.add(comissaoEntregaPassagem).add(comissaoOutros); comissaoPagar = comissaoPagar.add(comissaoBonificaoMetas); // - Descontos (Fixos e Eventuais) - Royaties - ISS retido comissaoPagar = comissaoPagar.add(rc.getDescontos().negate()).add(royaties.negate()).add(issRetido.negate()); rc.setComissaoPagar(comissaoPagar); return rc; } private List calculaReceitaComissao(PtovtaComissao ptovtaComissao, List receitasBoleto, Integer ultimodia, Integer mes, Integer ano) { List receitas = new ArrayList(); for (int dia = 1; dia <= ultimodia; dia++) { List list = verificaCalculoComissaoProDia(receitasBoleto, dia, mes); Calendar dataRegistro = Calendar.getInstance(); dataRegistro.set(Calendar.DAY_OF_MONTH, dia); dataRegistro.set(Calendar.MONTH, mes - 1); dataRegistro.set(Calendar.YEAR, ano); ComissaoReceita cr = new ComissaoReceita(); cr.setData(dataRegistro.getTime()); BigDecimal receitaComissao = BigDecimal.ZERO; BigDecimal receitaBPR = BigDecimal.ZERO; BigDecimal receitaGAP = BigDecimal.ZERO; BigDecimal internet = BigDecimal.ZERO; BigDecimal receitaExcessoBagagem = BigDecimal.ZERO; BigDecimal receitaSeguroOpcional = BigDecimal.ZERO; BigDecimal receitaSeguroOutros = BigDecimal.ZERO; BigDecimal cancelados = BigDecimal.ZERO; BigDecimal devolvidos = BigDecimal.ZERO; BigDecimal devolvidosOrigem = BigDecimal.ZERO; BigDecimal canceladosGAP = BigDecimal.ZERO; BigDecimal devolvidosGAP = BigDecimal.ZERO; BigDecimal devolvidosGAPOrigem = BigDecimal.ZERO; BigDecimal gapImpressa = BigDecimal.ZERO; int contImpressa = 0; // Receita Total -- bruta/liquida - abatimento do valor do icms boolean isReceitaLiquida = false; Receita receita = Receita.getByValor(ptovtaComissao.getReceita()); if (receita.equals(Receita.RECEITALIQUIDA)) { isReceitaLiquida = true; } for (BoletoComissao rcc : list) { IndStatusBoleto statusBoleto = IndStatusBoleto.valueOf(rcc.getIndstatusboleto()); BigDecimal receitaItem = BigDecimal.ZERO; BigDecimal receitaDevItem = BigDecimal.ZERO; // Totais if (ptovtaComissao.getTarifaReceita()) { receitaItem = receitaItem.add(rcc.getValorpagado()); } if (ptovtaComissao.getTaxaReceita()) { receitaItem = receitaItem.add(rcc.getEmbarque()); } if (ptovtaComissao.getSeguroReceita()) { receitaItem = receitaItem.add(rcc.getSeguro()); } if (ptovtaComissao.getPedagioReceita()) { receitaItem = receitaItem.add(rcc.getPedagio()); } // Totais de Devolução / Cancelamento if (ptovtaComissao.getTarifaDev()) { receitaDevItem = receitaDevItem.add(rcc.getValorpagado()); } if (ptovtaComissao.getTaxaDev()) { receitaDevItem = receitaDevItem.add(rcc.getEmbarque()); } if (ptovtaComissao.getSeguroDev()) { receitaDevItem = receitaDevItem.add(rcc.getSeguro()); } if (ptovtaComissao.getPedagioDev()) { receitaDevItem = receitaDevItem.add(rcc.getPedagio()); } // Calculo de ICMS sobre o valor do bilhete if (isReceitaLiquida) { BigDecimal icsm = BigDecimal.ZERO; icsm = receitaItem.multiply(rcc.getIcmsBase().divide(CEM)); receitaItem = receitaItem.add(icsm.negate()); BigDecimal icsmDev = BigDecimal.ZERO; icsmDev = receitaDevItem.multiply(rcc.getIcmsBase().divide(CEM)); receitaDevItem = receitaDevItem.add(icsmDev.negate()); } // Boletos impressos no punto venta if (statusBoleto.equals(IndStatusBoleto.E)) { contImpressa++; gapImpressa = gapImpressa.add(receitaItem); } else { // Receitas calculadas sempre receitaExcessoBagagem = receitaExcessoBagagem.add(rcc.getExcessoBagagem()); receitaSeguroOpcional = receitaSeguroOpcional.add(rcc.getSeguroOpcional()); receitaSeguroOutros = receitaSeguroOutros.add(rcc.getSeguroOutros()); // Receita GAP if (rcc.getTipoVenta().equals(Constantes.TPV_BOLETO_REMOTO.intValue())) { receitaGAP = receitaGAP.add(receitaItem); } // Internet else if (rcc.getTipoVenta().equals(Constantes.TPV_POR_INTERNET.intValue())) { internet = internet.add(receitaItem); } // Receita BPR else { receitaBPR = receitaBPR.add(receitaItem); } } if (statusBoleto.equals(IndStatusBoleto.C)) { // Devolução Receita if (rcc.getMotivoCancelacionId().equals(Constantes.MVO_CANCEL_DEVOLUCAO)) { // Devolução Receita GAP if (rcc.getTipoVenta().equals(Constantes.TPV_BOLETO_REMOTO.intValue())) { // Impresso Venta de otro punto venta if (rcc.isPtoVtaOrigem()) { devolvidosGAPOrigem = devolvidosGAPOrigem.add(receitaDevItem); } devolvidosGAP = devolvidosGAP.add(receitaDevItem); } else { // Impresso Venta de otro punto venta if (rcc.isPtoVtaOrigem()) { devolvidosOrigem = devolvidosOrigem.add(receitaDevItem); } devolvidos = devolvidos.add(receitaDevItem); } } // Cancelamento Receita else { // Cancelamento Receita GAP if (rcc.getTipoVenta().equals(Constantes.TPV_BOLETO_REMOTO.intValue())) { canceladosGAP = canceladosGAP.add(receitaDevItem); } else { cancelados = cancelados.add(receitaDevItem); } } } } cr.setCancelados(cancelados); cr.setCanceladosGAP(canceladosGAP); cr.setDevolvidos(devolvidos); cr.setDevolvidosGAP(devolvidosGAP); cr.setDevolucoesOrigem(devolvidosOrigem); cr.setDevolucoesOrigemGAP(devolvidosGAPOrigem); cr.setReceitaBPR(receitaBPR); cr.setReceitaExcessoBagagem(receitaExcessoBagagem); cr.setReceitaGAP(receitaGAP); cr.setReceitaSeguroOpcional(receitaSeguroOpcional); cr.setReceitaSeguroOutros(receitaSeguroOutros); cr.setInternet(internet); cr.setGapImpressa(gapImpressa); cr.setContImpressa(contImpressa); // Receita Comissão = Receita BPR + Receita GAP - GapImpressa - Internet // - Cancelados - Devoluções Origem - Cancelados GAP - Devoluções GAP Origem - Devoluções - Devoluções GAP receitaComissao = receitaComissao.add(receitaBPR).add(receitaGAP); receitaComissao = receitaComissao.add(gapImpressa.negate()).add(internet.negate()).add(cancelados.negate()); receitaComissao = receitaComissao.add(devolvidosOrigem.negate()).add(devolvidos.negate()).add(canceladosGAP.negate()); receitaComissao = receitaComissao.add(devolvidosGAPOrigem.negate()).add(devolvidosGAP.negate()); cr.setReceitaComissao(receitaComissao); receitas.add(cr); } return receitas; } private List verificaCalculoComissaoProDia(List list, Integer dia, Integer mes) { List aux = new ArrayList(); for (BoletoComissao rcc : list) { try { Calendar calendario = Calendar.getInstance(); calendario.setTime(DateUtil.getDateFromString(rcc.getDatavenda(), "dd-MM-yyyy")); int diaItem = calendario.get(Calendar.DAY_OF_MONTH); int mesItem = calendario.get(Calendar.MONTH) + 1; if (dia.equals(diaItem) && mes.equals(mesItem)) { aux.add(rcc); } } catch (ParseException e) { log.error("ERRO - ao converter data", e); } } return aux; } }