Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Qual padrão pode ser implementado nesse cenário

Tenho esse cenário que vejo a necessidade de melhorar o código, fiquei na dúvida de qual padrão resolveria o problema, os que achei mais prováveis são o Chain... e State, Qual poderia ser aplicado para resolver esses problemas de if`s, se tiver o caminho das pedras é ainda melhor?


    private void atualizaStatusFatura(List<Fatura> faturas) {

        for (Fatura fatura : faturas) {

//            se paga ou vencida não pode atualizar o status
            if (fatura.getStatus() != StatusFatura.PAGA && fatura.getStatus() != StatusFatura.VENCIDA) {

//                se estar aberta, só pode ir para fechada ou futura
                if (fatura.getStatus() == StatusFatura.ABERTA) {

                    if (jaFechou(fatura.getFechamento(), fatura.getVencimento())) {
                        fatura.setStatus(StatusFatura.FECHADA);
                        faturaRepository.save(fatura);
                        return;
                    }
                    if (ehFutura(fatura.getAbertura())) {
                        fatura.setStatus(StatusFatura.FUTURA);
                        faturaRepository.save(fatura);
                        return;
                    }
                    if (jaVenceu(fatura.getVencimento())) {
                        fatura.setStatus(StatusFatura.VENCIDA);
                        faturaRepository.save(fatura);
                        return;
                    }
                }

//                se é fechada só pode ir para vencida
                 if (fatura.getStatus() == StatusFatura.FECHADA) {
                    if (jaVenceu(fatura.getVencimento())) {
                        fatura.setStatus(StatusFatura.VENCIDA);
                        faturaRepository.save(fatura);
                        return;
                    }
                }

//                 se é futura só pode ir para aberta 
                if (fatura.getStatus() == StatusFatura.FUTURA) {
                    if (jaAbriu(fatura.getAbertura(), fatura.getFechamento())) {
                        fatura.setStatus(StatusFatura.ABERTA);
                        faturaRepository.save(fatura);
                        return;
                    }
                }
            }
        }
    }

    private boolean ehFutura(LocalDate abertura) {
        return abertura.isAfter(LocalDate.now());
    }

    private boolean jaAbriu(LocalDate abertura, LocalDate fechamento) {
        return LocalDate.now().isAfter(abertura.minusDays(1)) && LocalDate.now().isBefore(fechamento.plusDays(1));
    }

    private boolean jaVenceu(LocalDate vencimento) {
        return vencimento.isBefore(LocalDate.now());
    }

    private boolean jaFechou(LocalDate fechamento, LocalDate vencimento) {
        return LocalDate.now().isAfter(fechamento.minusDays(1)) && LocalDate.now().isBefore(vencimento.plusDays(1));
    }
3 respostas

Oi Jeferson,

Tá bem para o cenário do State, pois a lógica serve para atualizar uma fatura baseada em seu estado atual(fechada, vencida, etc.)

Bons estudos!

Além do State vc pode usar o Chain também. São 3 estados, mas para cada estado você poderia ter regras de negócio plugáveis e transitáveis, então você primeiro identifica o estado e dentro do estado encadeia as ações. Lembrando que, caso as ações não precisarem ser encadeadas (uma tendo conhecimento da outra) pode aplicar o Strategy.

solução!

Implementei o Chain acho que ficou melhor, ao menos o código melhorou, sem dúvida há outras formas, assim atendeu bem.

public abstract class FaturaAtualizou {

    protected FaturaAtualizou proximo;

    public FaturaAtualizou(FaturaAtualizou proximo) {
        this.proximo = proximo;
    }

    public abstract StatusFatura verifica(Fatura fatura);
}


public class FaturaEPagaOUVencida extends FaturaAtualizou {

    public FaturaEPagaOUVencida(FaturaAtualizou proximo) {
        super(proximo);
    }

    @Override
    public StatusFatura verifica(Fatura fatura) {
        if (fatura.getStatus() == StatusFatura.PAGA) {
            return StatusFatura.PAGA;
        }

        if (fatura.getStatus() == StatusFatura.VENCIDA) {
            return StatusFatura.VENCIDA;
        }

        return proximo.verifica(fatura);
    }

}

public class FaturaJaEAberta extends FaturaAtualizou {

    public FaturaJaEAberta(FaturaAtualizou proximo) {
        super(proximo);
    }

    @Override
    public StatusFatura verifica(Fatura fatura) {
        LocalDate hoje = LocalDate.now();

        if (fatura.getStatus() == StatusFatura.FUTURA 
                && hoje.isAfter(fatura.getAbertura().minusDays(1))
                && hoje.isBefore(fatura.getFechamento().plusDays(1))) {

            return StatusFatura.PAGA;
        }

        return proximo.verifica(fatura);
    }

}


public class FaturaJaEFechada extends FaturaAtualizou {

    public FaturaJaEFechada(FaturaAtualizou proximo) {
        super(proximo);
    }

    @Override
    public StatusFatura verifica(Fatura fatura) {

        LocalDate hoje = LocalDate.now();

        if (fatura.getStatus() == StatusFatura.ABERTA 
                && hoje.isAfter(fatura.getFechamento().minusDays(1))
                && hoje.isBefore(fatura.getVencimento().plusDays(1))) {

            return StatusFatura.FECHADA;
        }

        return proximo.verifica(fatura);
    }

}

// Classes omitidas ...

public class FaturaNaoAtualizou extends FaturaAtualizou {

    public FaturaNaoAtualizou() {
        super(null);
    }

    @Override
    public StatusFatura verifica(Fatura fatura) {
        return fatura.getStatus();
    }

}



    private void atualizaStatusFatura(List<Fatura> faturas) {

        for (Fatura fatura : faturas) {

            FaturaAtualizou faturaAtualizou = new FaturaEPagaOUVencida(
                    new FaturaJaEAberta(
                            new FaturaJaEFechada(
                                    new FaturaJaEFutura(
                                            new FaturaJaEVencida(
                                                    new FaturaNaoAtualizou())))));

            StatusFatura status = faturaAtualizou.verifica(fatura);

            if (status != fatura.getStatus()) {
                fatura.setStatus(status);
                faturaRepository.save(fatura);
            }
        }
    }