br.com.hslife.orcamento.service.FaturaCartaoService.java Source code

Java tutorial

Introduction

Here is the source code for br.com.hslife.orcamento.service.FaturaCartaoService.java

Source

/***
      
 Copyright (c) 2012 - 2020 Hrcules S. S. Jos
    
Este arquivo  parte do programa Oramento Domstico.
    
    
Oramento Domstico  um software livre; voc pode redistribui-lo e/ou 
    
modific-lo dentro dos termos da Licena Pblica Geral Menor GNU como 
    
publicada pela Fundao do Software Livre (FSF); na verso 2.1 da 
    
Licena.
    
    
Este programa  distribudo na esperana que possa ser til, 
    
mas SEM NENHUMA GARANTIA; sem uma garantia implcita de ADEQUAO a 
    
qualquer MERCADO ou APLICAO EM PARTICULAR. Veja a Licena Pblica 
    
Geral Menor GNU em portugus para maiores detalhes.
    
    
Voc deve ter recebido uma cpia da Licena Pblica Geral Menor GNU sob o 
    
nome de "LICENSE.TXT" junto com este programa, se no, acesse o site do
    
projeto no endereco https://github.com/herculeshssj/orcamento ou escreva 
    
para a Fundao do Software Livre(FSF) Inc., 51 Franklin St, Fifth Floor, 
    
Boston, MA  02110-1301, USA.
    
    
Para mais informaes sobre o programa Oramento Domstico e seu autor entre  
    
em contato pelo e-mail herculeshssj@outlook.com, ou ainda escreva para 
    
Hrcules S. S. Jos, Av. Ministro Lafaeyte de Andrade, 1683 - Bl. 3 Apt 404, 
    
Marco II - Nova Iguau, RJ, Brasil.
      
***/

package br.com.hslife.orcamento.service;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import br.com.hslife.orcamento.entity.CartaoCredito;
import br.com.hslife.orcamento.entity.Conta;
import br.com.hslife.orcamento.entity.ConversaoMoeda;
import br.com.hslife.orcamento.entity.FaturaCartao;
import br.com.hslife.orcamento.entity.LancamentoConta;
import br.com.hslife.orcamento.entity.LancamentoPeriodico;
import br.com.hslife.orcamento.entity.Moeda;
import br.com.hslife.orcamento.entity.Usuario;
import br.com.hslife.orcamento.enumeration.PeriodoLancamento;
import br.com.hslife.orcamento.enumeration.StatusFaturaCartao;
import br.com.hslife.orcamento.enumeration.StatusLancamento;
import br.com.hslife.orcamento.enumeration.StatusLancamentoConta;
import br.com.hslife.orcamento.enumeration.TipoLancamento;
import br.com.hslife.orcamento.enumeration.TipoLancamentoPeriodico;
import br.com.hslife.orcamento.exception.BusinessException;
import br.com.hslife.orcamento.facade.IFaturaCartao;
import br.com.hslife.orcamento.facade.ILancamentoPeriodico;
import br.com.hslife.orcamento.repository.FaturaCartaoRepository;
import br.com.hslife.orcamento.repository.LancamentoContaRepository;
import br.com.hslife.orcamento.util.Util;

@Service("faturaCartaoService")
public class FaturaCartaoService extends AbstractCRUDService<FaturaCartao> implements IFaturaCartao {

    @Autowired
    private FaturaCartaoRepository repository;

    @Autowired
    private LancamentoContaRepository lancamentoContaRepository;

    @Autowired
    private FechamentoPeriodoService fechamentoPeriodoService;

    @Autowired
    private ILancamentoPeriodico lancamentoPeriodicoService;

    public FaturaCartaoRepository getRepository() {
        this.repository.setSessionFactory(this.sessionFactory);
        return repository;
    }

    public ILancamentoPeriodico getLancamentoPeriodicoService() {
        return lancamentoPeriodicoService;
    }

    public FechamentoPeriodoService getFechamentoPeriodoService() {
        return fechamentoPeriodoService;
    }

    public LancamentoContaRepository getLancamentoContaRepository() {
        this.lancamentoContaRepository.setSessionFactory(this.sessionFactory);
        return lancamentoContaRepository;
    }

    @Override
    public void validar(FaturaCartao entity) {
        // Impede que haja mais de uma fatura com a mesma data de vencimento para o carto selecionado
        List<FaturaCartao> faturas = getRepository().findByContaAndDataVencimento(entity.getConta(),
                entity.getDataVencimento());
        if (faturas != null && !faturas.isEmpty()) {
            faturas.remove(entity);
            if (faturas.size() != 0)
                throw new BusinessException("Data de vencimento j informada para uma fatura cadastrada!");
        }
    }

    public double saldoDevedorUltimaFatura(CartaoCredito cartao) {
        FaturaCartao fatura = getRepository().lastFaturaCartaoFechada(cartao.getConta());
        if (fatura != null && !fatura.getStatusFaturaCartao().equals(StatusFaturaCartao.QUITADA)) {
            return fatura.getValorFatura() + fatura.getSaldoDevedor();
        } else {
            return 0.0;
        }
    }

    @SuppressWarnings("deprecation")
    @Override
    public void fecharFatura(FaturaCartao entity, List<Moeda> conversoes) {
        // Busca a fatura que ser fechada
        FaturaCartao faturaCartao = this.buscarPorID(entity.getId());

        // Obtm o saldo devedor da fatura atualmente fechada
        if (this.saldoDevedorUltimaFatura(entity.getConta().getCartaoCredito()) == 0.0)
            faturaCartao.setSaldoDevedor(faturaCartao.getSaldoDevedor()
                    + this.saldoDevedorUltimaFatura(entity.getConta().getCartaoCredito()));
        else
            faturaCartao.setSaldoDevedor(this.saldoDevedorUltimaFatura(entity.getConta().getCartaoCredito()));

        // Atribuies dos valores
        faturaCartao.setDataVencimento(entity.getDataVencimento());
        faturaCartao.setDataFechamento(entity.getDataFechamento());
        faturaCartao.setStatusFaturaCartao(StatusFaturaCartao.FECHADA);

        // Calcula o valor total da fatura
        double totalFatura = 0.0;
        for (Moeda moeda : conversoes) {
            if (moeda.isPadrao()) {
                moeda.setTotalConvertido(Util.arredondar(moeda.getTotal()));
            } else {
                moeda.setTotalConvertido(Util.arredondar(moeda.getTotal() * moeda.getTaxaConversao()));
            }
            totalFatura += moeda.getTotalConvertido();
        }
        // Adiciona ao total da fatura o valor da fatura vencida      
        faturaCartao.setValorFatura(totalFatura);
        faturaCartao.setValorMinimo(
                Util.arredondar((Math.abs(totalFatura + faturaCartao.getSaldoDevedor()) * 15) / 100)); // 15% do valor da fatura

        // Popula a lista de converses de moeda
        for (Moeda moeda : conversoes) {
            ConversaoMoeda conversao = new ConversaoMoeda();
            conversao.setFaturaCartao(faturaCartao);
            conversao.setMoeda(moeda);
            conversao.setTaxaConversao(moeda.getTaxaConversao());
            conversao.setValor(moeda.getTotalConvertido());
            faturaCartao.getConversoesMoeda().add(conversao);
        }

        // Altera o status da fatura atualmente fechada para VENCIDA      
        FaturaCartao faturaVencida = getRepository().lastFaturaCartaoFechada(entity.getConta());
        if (faturaVencida != null && !faturaVencida.getId().equals(faturaCartao.getId())
                && faturaVencida.getStatusFaturaCartao().equals(StatusFaturaCartao.FECHADA)) {
            faturaVencida.setStatusFaturaCartao(StatusFaturaCartao.VENCIDA);
            // Seta as informaes de pagamento da fatura
            faturaVencida.setDataPagamento(entity.getDataFechamento());
            faturaVencida.setValorPago(Math.abs(faturaVencida.getValorFatura()));
            faturaVencida.setValorMinimo(Util.arredondar((Math.abs(faturaVencida.getValorFatura()) * 15) / 100));
            // Salva a fatura
            getRepository().update(faturaVencida);
        }

        // Verifica se a fatura possui saldo total e saldo devedor zerado
        // Caso tenha, a fatura  automaticamento quitada
        if (faturaCartao.getSaldoDevedor() == 0 && faturaCartao.getValorFatura() == 0) {
            faturaCartao.setStatusFaturaCartao(StatusFaturaCartao.QUITADA);
        }

        // Salva a fatura do carto
        getRepository().update(faturaCartao);

        // Quita todos os lanamentos vinculados  fatura
        for (LancamentoConta lancamento : faturaCartao.getDetalheFatura()) {
            LancamentoConta l = getLancamentoContaRepository().findById(lancamento.getId());

            // Procura a taxa de converso para a moeda do lanamento
            double taxaConversao = 1.0000;
            for (ConversaoMoeda conversao : faturaCartao.getConversoesMoeda()) {
                if (conversao.getMoeda().equals(l.getMoeda())) {
                    taxaConversao = conversao.getTaxaConversao();
                    break;
                }
            }

            // Atualiza a taxa de converso para registrar corretamente os valores
            l.getTaxaConversao().atualizaTaxaConversao(l.getValorPago(), taxaConversao);

            if (l.getLancamentoPeriodico() != null) {
                // Delega a quitao do lanamento para a rotina de registro de pagamento de lanamentos peridicos
                getFechamentoPeriodoService().registrarPagamento(l);
            } else {
                l.setStatusLancamentoConta(StatusLancamentoConta.QUITADO);
                getLancamentoContaRepository().update(l);
            }
        }

        // Verifica se existe fatura futura para alterar o status
        if (getRepository().findNextFaturaCartaoFutura(entity.getConta()) == null) {
            // Cria a prxima fatura ABERTA
            FaturaCartao novaFatura = new FaturaCartao();
            novaFatura.setConta(entity.getConta());
            novaFatura.setStatusFaturaCartao(StatusFaturaCartao.ABERTA);
            // Data de vencimento da prxima fatura
            Calendar vencimento = Calendar.getInstance();
            vencimento.setTime(entity.getDataVencimento());
            vencimento.add(Calendar.MONTH, 1);
            novaFatura.setDataVencimento(vencimento.getTime());

            // Seta o ms e ano da fatura
            novaFatura.setMes(novaFatura.getDataVencimento().getMonth() + 1);
            novaFatura.setAno(novaFatura.getDataVencimento().getYear() + 1900);

            // Salva a nova fatura
            getRepository().save(novaFatura);
        } else {
            FaturaCartao novaFatura = getRepository().findNextFaturaCartaoFutura(entity.getConta());
            novaFatura.setStatusFaturaCartao(StatusFaturaCartao.ABERTA);
            getRepository().update(novaFatura);
        }
    }

    @Override
    public void reabrirFatura(FaturaCartao entity) {
        // Busca a fatura atualmente aberta e muda seu status para FUTURA
        FaturaCartao faturaAtual = getRepository().findFaturaCartaoAberta(entity.getConta());
        if (faturaAtual != null) {
            faturaAtual.setStatusFaturaCartao(StatusFaturaCartao.FUTURA);
            getRepository().update(faturaAtual);
        }

        // Busca a fatura que ser reaberta
        FaturaCartao fatura = getRepository().findById(entity.getId());

        // Atribuies dos valores
        //fatura.setDataFechamento(null);
        fatura.setStatusFaturaCartao(StatusFaturaCartao.ABERTA);

        // Salva a fatura do carto
        getRepository().update(fatura);

        // Reabre todos os lanamentos vinculados  fatura
        for (LancamentoConta lancamento : fatura.getDetalheFatura()) {
            LancamentoConta l = getLancamentoContaRepository().findById(lancamento.getId());
            l.setStatusLancamentoConta(StatusLancamentoConta.REGISTRADO);
            getLancamentoContaRepository().update(l);
        }
    }

    @Override
    public void quitarFaturaDebitoConta(FaturaCartao faturaCartao, Conta contaCorrente, double valorAQuitar,
            Date dataPagamento) {
        if (Math.abs(Util.arredondar(valorAQuitar)) < Math.abs(Util.arredondar(faturaCartao.getValorMinimo()))) {
            throw new BusinessException("Valor de pagamento no pode ser menor que o valor mnimo da fatura!");
        }

        if (Math.abs(Util.arredondar(valorAQuitar)) > Math
                .abs(Util.arredondar(faturaCartao.getValorFatura() + faturaCartao.getSaldoDevedor()))) {
            throw new BusinessException("No  possvel quitar um valor maior que o valor total da fatura!");
        }

        if (dataPagamento.before(contaCorrente.getDataAbertura())) {
            throw new BusinessException(
                    "Data de pagamento deve ser posterior a data de abertura da conta selecionada!");
        }

        // Traz a fatura e seta seus atributos
        FaturaCartao fatura = getRepository().findById(faturaCartao.getId());
        fatura.setStatusFaturaCartao(StatusFaturaCartao.QUITADA);
        fatura.setDataPagamento(dataPagamento);
        fatura.setValorPago(valorAQuitar);
        fatura.setValorMinimo(faturaCartao.getValorMinimo());

        // Cria o lanamento que ir quitar a fatura
        LancamentoConta lancamentoPagamento = new LancamentoConta();
        lancamentoPagamento.setConta(contaCorrente);
        lancamentoPagamento.setMoeda(contaCorrente.getMoeda());
        lancamentoPagamento.setDataPagamento(dataPagamento);
        lancamentoPagamento.setDescricao("Pagamento Fatura " + fatura.getLabel() + ", "
                + faturaCartao.getConta().getCartaoCredito().getDescricao());
        lancamentoPagamento.setStatusLancamentoConta(StatusLancamentoConta.QUITADO);
        lancamentoPagamento.setValorPago(valorAQuitar);
        lancamentoPagamento.setTipoLancamento(TipoLancamento.DESPESA);
        lancamentoPagamento.setCategoria(faturaCartao.getCategoriaSelecionada());
        lancamentoPagamento.setFavorecido(faturaCartao.getFavorecidoSelecionado());
        lancamentoPagamento.setMeioPagamento(faturaCartao.getMeioPagamentoSelecionado());

        // Determina o valor do saldo devedor
        double saldoDevedor = (faturaCartao.getValorFatura() + faturaCartao.getSaldoDevedor()) - valorAQuitar;

        // Salva o lanamento
        getLancamentoContaRepository().save(lancamentoPagamento);

        // Atribui o lanamento  fatura
        fatura.setLancamentoPagamento(lancamentoPagamento);

        // Salva a fatura paga
        getRepository().update(fatura);

        // Busca a fatura aberta e atribui o saldo devedor a ela. Depois salva
        FaturaCartao faturaAtual = getRepository().findFaturaCartaoAberta(faturaCartao.getConta());
        faturaAtual.setSaldoDevedor(saldoDevedor);
        getRepository().update(faturaAtual);
    }

    @Override
    public void quitarFaturaParcelamento(FaturaCartao faturaCartao, int quantParcelas, Date dataParcelamento) {

        /* Efetua a quitao da fatura */
        FaturaCartao fatura = getRepository().findById(faturaCartao.getId());
        fatura.setStatusFaturaCartao(StatusFaturaCartao.QUITADA);
        fatura.setDataPagamento(dataParcelamento);
        fatura.setValorPago(faturaCartao.getValorFatura() + faturaCartao.getSaldoDevedor());
        fatura.setValorMinimo(faturaCartao.getValorMinimo());

        // Salva a fatura paga
        getRepository().update(fatura);

        /* Efetua o parcelamento da fatura */

        // Traz as informaes da fatura atualmente aberta
        FaturaCartao faturaAberta = getRepository().findFaturaCartaoAberta(faturaCartao.getConta());

        // Determina a data de fechamento da fatura atual
        Calendar temp = Calendar.getInstance();
        temp.setTime(faturaAberta.getDataVencimento());
        if (faturaAberta.getConta().getCartaoCredito().getDiaFechamentoFatura() < faturaAberta.getConta()
                .getCartaoCredito().getDiaVencimentoFatura()) {
            temp.set(Calendar.DAY_OF_MONTH, faturaAberta.getConta().getCartaoCredito().getDiaFechamentoFatura());
        } else {
            temp.add(Calendar.MONTH, 1);
            temp.set(Calendar.DAY_OF_MONTH, faturaAberta.getConta().getCartaoCredito().getDiaFechamentoFatura());
        }

        LancamentoPeriodico parcelamentoFatura = new LancamentoPeriodico();
        parcelamentoFatura.setConta(faturaCartao.getConta());
        parcelamentoFatura.setDataAquisicao(dataParcelamento);
        parcelamentoFatura.setDataPrimeiraParcela(temp.getTime());
        parcelamentoFatura
                .setDescricao("Parcelamento Fatura " + faturaCartao.getMes() + "/" + faturaCartao.getAno());
        parcelamentoFatura.setDiaVencimento(faturaCartao.getConta().getCartaoCredito().getDiaFechamentoFatura());
        parcelamentoFatura.setMoeda(faturaCartao.getConta().getMoeda());
        parcelamentoFatura.setPeriodoLancamento(PeriodoLancamento.MENSAL);
        parcelamentoFatura.setStatusLancamento(StatusLancamento.ATIVO);
        parcelamentoFatura.setTipoLancamento(TipoLancamento.DESPESA);
        parcelamentoFatura.setTipoLancamentoPeriodico(TipoLancamentoPeriodico.PARCELADO);
        parcelamentoFatura.setTotalParcela(quantParcelas);
        parcelamentoFatura.setUsuario(faturaCartao.getConta().getUsuario());
        parcelamentoFatura.setValorCompra(fatura.getValorPago());
        parcelamentoFatura.setValorParcela(Util.arredondar(fatura.getValorPago() / quantParcelas));
        parcelamentoFatura.setCategoria(faturaCartao.getCategoriaSelecionada());
        parcelamentoFatura.setFavorecido(faturaCartao.getFavorecidoSelecionado());
        parcelamentoFatura.setMeioPagamento(faturaCartao.getMeioPagamentoSelecionado());
        getLancamentoPeriodicoService().cadastrar(parcelamentoFatura);
    }

    @Override
    public void quitarFaturaLancamentoSelecionado(FaturaCartao faturaCartao, LancamentoConta lancamentoConta) {
        // Verifica se o lanamento selecionado j foi vinculado com outra fatura
        if (getLancamentoContaRepository().existsLinkagePagamentoFaturaCartao(lancamentoConta)) {
            throw new BusinessException("Lanamento selecionado j foi usado para quitar outra fatura!");
        }

        // Verifica se o valor do lanamento selecionado  menor que o valor mnimo da fatura
        if (Math.abs(Util.arredondar(lancamentoConta.getValorPago())) < Math
                .abs(Util.arredondar(faturaCartao.getValorMinimo()))) {
            throw new BusinessException("Valor de pagamento no pode ser menor que o valor mnimo da fatura!");
        }

        // Verifica se o valor do lanamento selecionado  maior que o valor total da fatura
        if (Math.abs(Util.arredondar(lancamentoConta.getValorPago())) > Math
                .abs(Util.arredondar(faturaCartao.getValorFatura() + faturaCartao.getSaldoDevedor()))) {
            throw new BusinessException("No  possvel quitar um valor maior que o valor total da fatura!");
        }

        FaturaCartao fatura = getRepository().findById(faturaCartao.getId());
        fatura.setStatusFaturaCartao(StatusFaturaCartao.QUITADA);
        fatura.setDataPagamento(lancamentoConta.getDataPagamento());
        fatura.setValorPago(lancamentoConta.getValorPago());
        fatura.setValorMinimo(faturaCartao.getValorMinimo());

        double saldoDevedor = (faturaCartao.getValorFatura() + faturaCartao.getSaldoDevedor())
                - lancamentoConta.getValorPago();

        // Atribui o lanamento  fatura
        fatura.setLancamentoPagamento(lancamentoConta);

        // Salva a fatura paga
        getRepository().update(fatura);

        // Busca a fatura aberta e atribui o saldo devedor a ela. Depois salva
        FaturaCartao faturaAtual = getRepository().findFaturaCartaoAberta(faturaCartao.getConta());
        faturaAtual.setSaldoDevedor(saldoDevedor);
        getRepository().update(faturaAtual);
    }

    @Override
    public List<FaturaCartao> buscarTodosPorCartaoCredito(Conta conta) {
        return getRepository().findAllByCartaoCredito(conta);
    }

    @Override
    public List<FaturaCartao> buscarTodos() {
        return getRepository().findAll();
    }

    @Override
    public List<FaturaCartao> buscarTodosPorUsuario(Usuario usuario) {
        return getRepository().findAllByUsuario(usuario);
    }

    @Override
    public List<FaturaCartao> buscarPorCartaoCreditoEStatusFatura(CartaoCredito cartao,
            StatusFaturaCartao statusFatura) {
        return getRepository().findByContaAndStatusFatura(cartao.getConta(), statusFatura);
    }

    @Override
    public List<FaturaCartao> buscarTodosPorContaOrdenadoPorMesEAno(Conta conta) {
        return getRepository().findAllByContaOrderedByMesAndAno(conta);
    }

    @Override
    public List<FaturaCartao> buscarTodosPorContaEAnoOrdenadosPorMesAno(Conta conta, int ano) {
        return getRepository().findAllByContaAndAnoOrderedByMesAndAno(conta, ano);
    }
}