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

Java tutorial

Introduction

Here is the source code for br.com.hslife.orcamento.service.FechamentoPeriodoService.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.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import br.com.hslife.orcamento.entity.Conta;
import br.com.hslife.orcamento.entity.FechamentoPeriodo;
import br.com.hslife.orcamento.entity.LancamentoConta;
import br.com.hslife.orcamento.entity.LancamentoPeriodico;
import br.com.hslife.orcamento.enumeration.IncrementoClonagemLancamento;
import br.com.hslife.orcamento.enumeration.OperacaoConta;
import br.com.hslife.orcamento.enumeration.StatusLancamento;
import br.com.hslife.orcamento.enumeration.StatusLancamentoConta;
import br.com.hslife.orcamento.enumeration.TipoLancamentoPeriodico;
import br.com.hslife.orcamento.exception.ApplicationException;
import br.com.hslife.orcamento.exception.BusinessException;
import br.com.hslife.orcamento.facade.IFechamentoPeriodo;
import br.com.hslife.orcamento.model.CriterioBuscaLancamentoConta;
import br.com.hslife.orcamento.repository.FechamentoPeriodoRepository;
import br.com.hslife.orcamento.repository.LancamentoContaRepository;
import br.com.hslife.orcamento.repository.LancamentoPeriodicoRepository;
import br.com.hslife.orcamento.util.LancamentoContaUtil;
import br.com.hslife.orcamento.util.Util;

@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { ApplicationException.class })
public class FechamentoPeriodoService implements IFechamentoPeriodo {

    @Autowired
    private SessionFactory sessionFactory;

    @Autowired
    private FechamentoPeriodoRepository repository;

    @Autowired
    private LancamentoContaRepository lancamentoContaRepository;

    @Autowired
    private LancamentoPeriodicoRepository lancamentoPeriodicoRepository;

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

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

    public LancamentoPeriodicoRepository getLancamentoPeriodicoRepository() {
        this.lancamentoPeriodicoRepository.setSessionFactory(this.sessionFactory);
        return lancamentoPeriodicoRepository;
    }

    public FechamentoPeriodo buscarUltimoFechamentoPeriodoPorConta(Conta conta) {
        return getRepository().findUltimoFechamentoByConta(conta);
    }

    public List<FechamentoPeriodo> buscarPorContaEOperacaoConta(Conta conta, OperacaoConta operacaoConta) {
        return getRepository().findByContaAndOperacaoConta(conta, operacaoConta);
    }

    public void fecharPeriodo(Date dataFechamento, Conta conta) {
        this.fecharPeriodo(dataFechamento, conta, null, null);
    }

    public void fecharPeriodo(Date dataFechamento, Conta conta, List<LancamentoPeriodico> lancamentosPeriodicos) {
        this.fecharPeriodo(dataFechamento, conta, null, lancamentosPeriodicos);
    }

    public void fecharPeriodo(FechamentoPeriodo fechamentoPeriodo,
            List<LancamentoPeriodico> lancamentosPeriodicos) {
        this.fecharPeriodo(fechamentoPeriodo.getData(), fechamentoPeriodo.getConta(), fechamentoPeriodo,
                lancamentosPeriodicos);
    }

    @SuppressWarnings("deprecation")
    public void fecharPeriodo(Date dataFechamento, Conta conta, FechamentoPeriodo fechamentoReaberto,
            List<LancamentoPeriodico> lancamentosPeriodicos) {
        // Obtm-se o ltimo fechamento realizado
        FechamentoPeriodo fechamentoAnterior;
        if (fechamentoReaberto == null)
            fechamentoAnterior = getRepository().findUltimoFechamentoByConta(conta);
        else
            fechamentoAnterior = getRepository().findFechamentoPeriodoAnterior(fechamentoReaberto);

        double saldoFechamentoAnterior = 0;

        if (fechamentoAnterior == null) {
            saldoFechamentoAnterior = conta.getSaldoInicial();
        } else {
            saldoFechamentoAnterior = fechamentoAnterior.getSaldo();
        }

        // Incrementa a data do fechamento anterior
        Calendar temp = Calendar.getInstance();
        if (fechamentoAnterior != null) {
            temp.setTime(fechamentoAnterior.getData());
            temp.add(Calendar.DAY_OF_YEAR, 1);
        } else
            temp.setTime(conta.getDataAbertura());

        // Calcula o saldo do perodo
        CriterioBuscaLancamentoConta criterio = new CriterioBuscaLancamentoConta();
        criterio.setConta(conta);
        criterio.setDescricao("");
        criterio.setDataInicio(temp.getTime());
        criterio.setDataFim(dataFechamento);
        criterio.setStatusLancamentoConta(
                new StatusLancamentoConta[] { StatusLancamentoConta.REGISTRADO, StatusLancamentoConta.QUITADO });
        double saldoFechamento = LancamentoContaUtil
                .calcularSaldoLancamentos(getLancamentoContaRepository().findByCriterioBusca(criterio));

        // Cria o novo fechamento para a conta
        FechamentoPeriodo novoFechamento = new FechamentoPeriodo();
        if (fechamentoReaberto == null) {
            // Antes de prosseguir, verifica se no existem perodos reabertos
            List<FechamentoPeriodo> fechamentosReabertos = getRepository().findByContaAndOperacaoConta(conta,
                    OperacaoConta.REABERTURA);
            if (fechamentosReabertos != null && !fechamentosReabertos.isEmpty()) {
                // TODO refatorara para uma especificao que valide a possibilidade de fechamento
                throw new BusinessException("No  possvel fechar! Existem perodos anteriores reabertos!");
            }

            novoFechamento.setConta(conta);
            novoFechamento.setData(dataFechamento);
            novoFechamento.setOperacao(OperacaoConta.FECHAMENTO);
            novoFechamento.setDataAlteracao(new Date());
            novoFechamento.setSaldo(saldoFechamentoAnterior + saldoFechamento);

            // Obtm o ms e ano da data de fechamento
            temp.setTime(dataFechamento);
            novoFechamento.setMes(temp.getTime().getMonth() + 1);
            novoFechamento.setAno(temp.get(Calendar.YEAR));

            // Salva o fechamento
            getRepository().save(novoFechamento);
        } else {
            // Antes de prosseguir, verifica se o perodo selecionado no contm
            // perodos reabertos anteriores
            List<FechamentoPeriodo> fechamentosAnterioresReabertos = getRepository()
                    .findFechamentosAnterioresReabertos(fechamentoReaberto);
            if (fechamentosAnterioresReabertos != null && !fechamentosAnterioresReabertos.isEmpty()) {
                // TODO refatorar para uma especificao que valide a possibilidade de fechamento
                throw new BusinessException("No  possvel fechar! Existem perodos anteriores reabertos!");
            }

            // Altera os dados do fechamento j existente
            fechamentoReaberto.setOperacao(OperacaoConta.FECHAMENTO);
            fechamentoReaberto.setDataAlteracao(new Date());
            fechamentoReaberto.setSaldo(saldoFechamentoAnterior + saldoFechamento);

            // Salva o fechamento
            getRepository().update(fechamentoReaberto);
        }

        // Quita os lanamentos do perodo
        for (LancamentoConta l : getLancamentoContaRepository().findByCriterioBusca(criterio)) {
            l.setStatusLancamentoConta(StatusLancamentoConta.QUITADO);
            if (fechamentoReaberto == null)
                l.setFechamentoPeriodo(novoFechamento);
            else
                l.setFechamentoPeriodo(fechamentoReaberto);

            if (lancamentosPeriodicos != null && lancamentosPeriodicos.contains(l.getLancamentoPeriodico())) {
                this.registrarPagamento(l);
            } else {
                getLancamentoContaRepository().update(l);
            }
        }
    }

    public void reabrirPeriodo(FechamentoPeriodo entity) {
        // Busca os fechamentos posteriores ao fechamento selecionado
        List<FechamentoPeriodo> fechamentosPosteriores = getRepository().findFechamentosPosteriores(entity);

        // Itera a lista de fechamentos realizando a reabertura dos mesmos e dos lanamentos vinculados
        for (FechamentoPeriodo fechamentoPeriodo : fechamentosPosteriores) {
            FechamentoPeriodo fechamento = getRepository().findById(fechamentoPeriodo.getId());
            fechamento.setOperacao(OperacaoConta.REABERTURA);
            fechamento.setDataAlteracao(new Date());
            getRepository().update(fechamento);

            for (LancamentoConta l : fechamento.getLancamentos()) {
                l.setStatusLancamentoConta(StatusLancamentoConta.REGISTRADO);
                getLancamentoContaRepository().update(l);
            }
        }
    }

    @SuppressWarnings("deprecation")
    public void registrarPagamento(LancamentoConta pagamentoPeriodo) {
        pagamentoPeriodo.setStatusLancamentoConta(StatusLancamentoConta.QUITADO);

        // Atualiza o pagamento
        getLancamentoContaRepository().update(pagamentoPeriodo);

        // Gera o prximo pagamento para os lanamentos fixos
        if (pagamentoPeriodo.getLancamentoPeriodico().getTipoLancamentoPeriodico()
                .equals(TipoLancamentoPeriodico.FIXO)
                && pagamentoPeriodo.getLancamentoPeriodico().getStatusLancamento().equals(StatusLancamento.ATIVO)) {

            // Busca o pagamento mais recente
            LancamentoConta ultimaMensalidade = getLancamentoContaRepository()
                    .findLastGeneratedPagamentoPeriodo(pagamentoPeriodo.getLancamentoPeriodico());

            LancamentoConta proximaMensalidade;

            if (ultimaMensalidade == null) {
                proximaMensalidade = new LancamentoConta(pagamentoPeriodo);
                proximaMensalidade.setDataVencimento(new Date());
            } else {
                proximaMensalidade = ultimaMensalidade.clonarLancamentos(1, IncrementoClonagemLancamento.NENHUM)
                        .get(0);
            }

            proximaMensalidade.setLancamentoPeriodico(pagamentoPeriodo.getLancamentoPeriodico());

            // Incrementa a data de vencimento independente do valor informado
            proximaMensalidade.setDataVencimento(proximaMensalidade.getLancamentoPeriodico().getPeriodoLancamento()
                    .getDataPeriodo(proximaMensalidade.getDataVencimento()));
            // Corrige o dia de vencimento
            proximaMensalidade.getDataVencimento()
                    .setDate(proximaMensalidade.getLancamentoPeriodico().getDiaVencimento());

            proximaMensalidade.setAno(proximaMensalidade.getDataVencimento().getYear() + 1900);
            proximaMensalidade.setPeriodo(proximaMensalidade.getDataVencimento().getMonth() + 1);
            proximaMensalidade.setDataPagamento(proximaMensalidade.getDataVencimento());
            proximaMensalidade.setValorPago(proximaMensalidade.getLancamentoPeriodico().getValorParcela());

            // Define a descrio definitiva do lanamento a ser criado
            proximaMensalidade.setDescricao(proximaMensalidade.getLancamentoPeriodico().getDescricao()
                    + " - Perodo " + proximaMensalidade.getPeriodo() + " / " + proximaMensalidade.getAno()
                    + ", vencimento para "
                    + Util.formataDataHora(proximaMensalidade.getDataVencimento(), Util.DATA));

            // Atualiza a taxa de converso
            if (proximaMensalidade.getTaxaConversao() != null) {
                proximaMensalidade.getTaxaConversao().atualizaTaxaConversao(proximaMensalidade.getValorPago());
            }

            getLancamentoContaRepository().save(proximaMensalidade);

        } else {
            // Verifica se o lanamento peridico vinculado j pode ser encerrado.
            pagamentoPeriodo.getLancamentoPeriodico().setPagamentos(getLancamentoContaRepository()
                    .findByLancamentoPeriodico(pagamentoPeriodo.getLancamentoPeriodico()));
            if (pagamentoPeriodo.getLancamentoPeriodico().podeEncerrar()) {
                pagamentoPeriodo.getLancamentoPeriodico().setStatusLancamento(StatusLancamento.ENCERRADO);
                getLancamentoPeriodicoRepository().update(pagamentoPeriodo.getLancamentoPeriodico());
            }
        }
    }

    @Override
    public FechamentoPeriodo buscarFechamentoPeriodoAnterior(FechamentoPeriodo fechamentoPeriodo) {
        return getRepository().findFechamentoPeriodoAnterior(fechamentoPeriodo);
    }

    @Override
    public FechamentoPeriodo buscarUltimoFechamentoConta(Conta conta) {
        return getRepository().findUltimoFechamentoByConta(conta);
    }

    @Override
    public List<FechamentoPeriodo> buscarTodosFechamentoPorConta(Conta conta) {
        return getRepository().findAllByConta(conta);
    }

    @Override
    public FechamentoPeriodo buscarFechamentoPorID(Long id) {
        return getRepository().findById(id);
    }

    public double saldoUltimoFechamento(Conta conta) {
        FechamentoPeriodo ultimoFechamento = getRepository().findUltimoFechamentoByConta(conta);
        if (ultimoFechamento == null) {
            return conta.getSaldoInicial();
        } else {
            return ultimoFechamento.getSaldo();
        }
    }

    @Override
    public FechamentoPeriodo buscarUltimoFechamentoPeriodoAntesDataPorContaEOperacao(Conta conta, Date data,
            OperacaoConta operacao) {
        return getRepository().findLastFechamentoPeriodoBeforeDateByContaAndOperacao(conta, data, operacao);
    }
}