sábado, 25 de julho de 2020

Contas Pagar/Receber - Parte XXIV - Ajustes e Melhorias

Introdução
Nesse vigésimo quarto post vou fazer algumas correções e melhorias na nossa aplicação.

Correção na Execução do BPM 
No post anterior eu identifiquei que tinha uma falha, antes de finalizar a execução do fluxo a conta lançada estava aparecendo, isso aconteceu porque eu utilizei o próprio atributo autorizado da entidade LancamentoEntity na resposta de aprovação de cada um dos cargos. Vou corrigir fazendo a seguinte alteração, primeiro criando uma variável transient no LancamentoEntity conforme a seguir:
LancamentoEntity.java:
/* CODIGO ANTERIOR OCULTADO */

@Transient
private transient boolean aprovado;
/* CODIGO OMITIDO */
public boolean isAprovado() {
return aprovado;
}

public void setAprovado(boolean aprovado) {
this.aprovado = aprovado;
}
/* CODIGO POSTERIOR OMITIDO */
E no lancamentoData.xhtml faço a alteração apontando para o atributo acima:
lancamentoData.xhtml:
/* CODIGO ANTERIOR OMITIDO */
<h:panelGroup rendered="#{lancamentoDataAction.idDynamicAction eq 'idAvaliarLancamento'}">
<a:outputLabel value="#{e:bundle('label.aprovado')}" for="idLancamentoAprovacao"/>
<br/>
<a:toggleSwitch id="idLancamentoAprovacao"
label="#{e:bundle('label.aprovado')}"
value="#{lancamentoDataAction.entity.aprovado}"/>
</h:panelGroup>
/* CODIGO POSTERIOR OMITIDO */
E pra finalizar vou alterar o LancamentoObserver, mudando o evento para Before e setar a variável de aprovação no fluxo conforme o atributo aprovado no lugar de autorizado conforme a seguir:
LancamentoObserver.java:
/* CODIGO ANTERIOR OMITIDO */
private void avaliacao(@Observes @JArchEventDynamicBefore("idAvaliarLancamento") LancamentoEntity lancamento,
UserInformation userInformation, TaskService taskService) {
UsuarioEntity usuarioLogado = userInformation.get(UsuarioEntity.
class);

String variavelAprovacao;

if (usuarioLogado.getCargo() == CargoType.SUPERVISOR) {
variavelAprovacao =
"aprovadoSupervisor";
} else if (usuarioLogado.getCargo() == CargoType.GERENTE) {
variavelAprovacao =
"aprovadoGerente";
} else {
variavelAprovacao =
"aprovadoDiretor";
}

taskService.complete(lancamento.getTask().get().getId()
,
Map.of(variavelAprovacao, lancamento.isAprovado(),
"valorLancamento", lancamento.getValor().doubleValue()));
}
/* CODIGO POSTERIOR OMITIDO */
E no bundle:
bundle_pt_BR.properties:

label.aprovado=Aprovado

Após a compilação e execução de uma nova instância no fluxo:

E entrando na tela de lançamento não aparece a conta que está em analise no fluxo:

Filtro Relatório Lançamento
O relatório de lançamento tem um falha, não está filtrando o tipo de lançamento (Pagar / Receber). Vou alterar o filtro do relatório para contemplar o tipo de laçamento e também para filtrar somente os lançamentos autorizados. Vou adicionar no filtro do método selecionaDados():
RelatorioLancamentoAction.java:
/* CODIGO ANTERIOR OMITIDO */
private Collection<LancamentoEntity> selecionaDados() {
boolean filtraBanco = !excetoBanco && bancos != null && !bancos.isEmpty();
boolean filtraExcetoBanco = excetoBanco && bancos != null && !bancos.isEmpty();
boolean filtraCentroCusto = !excetoCentroCusto && centroCustos != null && !centroCustos.isEmpty();
boolean filtraExcetoCentroCusto = excetoCentroCusto && centroCustos != null && !centroCustos.isEmpty();
boolean filtraCategoria = !excetoCategoria && categorias != null && !categorias.isEmpty();
boolean filtraExcetoCategoria = excetoCategoria && categorias != null && !categorias.isEmpty();
boolean filtraPessoa = !excetoPessoa && pessoas != null && !pessoas.isEmpty();
boolean filtraExcetoPessoa = excetoPessoa && pessoas != null && !pessoas.isEmpty();

return lancamentoFacade
.clientJpaql()
.where()
.contains(filtraBanco
, LancamentoEntity_.banco, bancos)
.and(filtraBanco)
.notContains(filtraExcetoBanco
, LancamentoEntity_.banco, bancos)
.and(filtraExcetoBanco)
.contains(filtraCentroCusto
, LancamentoEntity_.centroCusto, centroCustos)
.and(filtraCentroCusto)
.notContains(filtraExcetoCentroCusto
, LancamentoEntity_.centroCusto, centroCustos)
.and(filtraExcetoCentroCusto)
.contains(filtraCategoria
, LancamentoEntity_.categoria, categorias)
.and(filtraCategoria)
.notContains(filtraExcetoCategoria
, LancamentoEntity_.categoria, categorias)
.and(filtraExcetoCategoria)
.contains(filtraPessoa
, LancamentoEntity_.pessoa, pessoas)
.and(filtraPessoa)
.notContains(filtraExcetoPessoa
, LancamentoEntity_.pessoa, pessoas)
.and(filtraExcetoPessoa)
.greaterOrEqualsThan(
vencimentoInicio != null, LancamentoEntity_.vencimento, vencimentoInicio)
.and(vencimentoInicio != null)
.lessOrEqualsThan(
vencimentoFim != null, LancamentoEntity_.vencimento, vencimentoFim)
.and(vencimentoFim != null)
.equalsTo(LancamentoEntity_.
tipoLancamento, tipoLancamento)
.and()

.equalsTo(LancamentoEntity_.
autorizado, true)
.collect()
.list()
;
}
/* CODIGO POSTERIOR OMITIDO */
Agora ao tentar imprimir o relatório:

Filtro Alertas e Mensagens
Os alertas e mensagens gerados também não possuí o filtro de contas autorizadas. Então vou corrigir isso também. Para isso preciso alterar os métodos contaPagarAbertoAte() e contaPagarAbertoEm() do LancamentoFacade adicionado o filtro de autorizado.
LancamentoFacade.java:
/* CODIGO ANTERIOR OMITIDO */

public Collection<LancamentoEntity> contaPagarAbertoAte(LocalDate vencimento) {
return clientJpaql()
.where()
.equalsTo(LancamentoEntity_.
aberto, true)
.and()
.equalsTo(LancamentoEntity_.
tipoLancamento, TipoLancamentoType.PAGAR)
.and()
.equalsTo(LancamentoEntity_.autorizado, true)
.and()
.lessOrEqualsThan(LancamentoEntity_.vencimento, vencimento)
.collect()
.list()
;
}

public Collection<LancamentoEntity> contaPagarAbertoEm(LocalDate vencimento) {
return clientJpaql()
.where()
.equalsTo(LancamentoEntity_.
aberto, true)
.and()
.equalsTo(LancamentoEntity_.
tipoLancamento, TipoLancamentoType.PAGAR)
.and()
.equalsTo(LancamentoEntity_.autorizado, true)

.and()
.equalsTo(LancamentoEntity_.
vencimento, vencimento)
.collect()
.list()
;
}
/* CODIGO ANTERIOR OMITIDO */

Alterando Ícones Dashboard
Vou alterar o ícones dos cards dos lançamentos de contas pagar e receber para ficar com uma aparência melhor:
bemVindo.xhtml:

<e:dashboardUnity icon="fa fa-coins fa-5x"
classMinHeight="h100"
styleIcon="color: orange"
title="#{bemVindoAction.quantidadeContaPagar}"
labelButtonLink="#{e:bundle('label.acessar')}"
link="../lancamento/lancamentoList.jsf?tipo=PAGAR"
descriptionLink="#{e:bundle('message.acessarPagina')}"/>

<e:dashboardUnity icon="fa fa-hand-holding-usd fa-5x"
classMinHeight="h100"
styleIcon="color: red"
title="#{bemVindoAction.quantidadeContaPago}"
labelButtonLink="#{e:bundle('label.acessar')}"
link="../lancamento/lancamentoList.jsf?tipo=PAGAR"
descriptionLink="#{e:bundle('message.acessarPagina')}"/>

<e:dashboardUnity icon="fa fa-donate fa-5x"
classMinHeight="h100"
styleIcon="color: blue"
title="#{bemVindoAction.quantidadeContaReceber}"
labelButtonLink="#{e:bundle('label.acessar')}"
link="../lancamento/lancamentoList.jsf?tipo=RECECER"
descriptionLink="#{e:bundle('message.acessarPagina')}"/>

<e:dashboardUnity icon="fa fa-comments-dollar fa-5x"
classMinHeight="h100"
styleIcon="color: green"
title="#{bemVindoAction.quantidadeContaRecebido}"
labelButtonLink="#{e:bundle('label.acessar')}"
link="../lancamento/lancamentoList.jsf?tipo=RECEBER"
descriptionLink="#{e:bundle('message.acessarPagina')}"/>

Agora a aparência ficou como:

Alterando Tempo Sessão
Atualmente a aplicação está com o tempo de 5 minutos para usuários Administrador, Operador e Supervisor e 1 minuto para usuários Gerente e Diretor. Vou alterar para 30 minutos e 10 minutos. Alterando primeiro o web.xml do contas-web:
web.xml:

<session-config>
<session-timeout>30</session-timeout>
</session-config>

E no LoginObserver ajusto para 10 minutos se cargos igual Gerente ou Diretor:

public class LoginObserver {

private void login(@Observes @JArchEventLoginAfter UsuarioEntity usuario, AlertaFacade alertaFacade, MensagemFacade mensagemFacade) {
alertaFacade.atualizaAlertaSessao();
mensagemFacade.atualizaMensagemSessao();

if (usuario.getCargo().equals(CargoType.DIRETOR) || usuario.getCargo().equals(CargoType.GERENTE)) {
JsfUtils.getSession().setMaxInactiveInterval(600);
}
}
}
Constant
Uma boa prática é definir String literal como variável do tipo final, principalmente aquelas que são utilizadas mais de uma vez. Por exemplo, no BPM defini o id do fluxo como process-avaliacao-conta. Essa mesma String é utilizada em mais de um lugar, dentro do LancamentoObserver e no AutorizacaoLancamentoListTaskAction. Então vou criar uma classe Constant dentro do pacote raiz no contas-client, somente para armazenar essas essas constants. 
Constant.java:

public final class Constant {
    public static final String PROCESS_AVALIACAO_CONTA = "process-avaliacao-conta";
private Constant() {

}

}
E substituo em todos os lugares que faziam referência conforme a seguir: 
LancamentoObserver.java:

runtimeService
.createProcessInstanceByKey(Constant.PROCESS_AVALIACAO_CONTA)
.businessKey(lancamento.getId().toString())
.setVariable("descricao", lancamento.getDescricao())
.setVariable("valor", lancamento.getValor().doubleValue())
.setVariable("vencimento", lancamento.getVencimento())
.execute();
AutorizacaoLancamentoListTaskAction:

TaskQuery taskQuery = processEngine
.getTaskService()
.createTaskQuery()
.processDefinitionKey(Constant.PROCESS_AVALIACAO_CONTA)
.active()
.initializeFormKeys()
.withCandidateGroups()
.taskCandidateGroup(usuarioLogado.getCargo().name())
.includeAssignedTasks();
Fica como dica sempre adotar esse mesmo procedimento para quaisquer String literais com mais de uma ocorrência.
Cargo Usuário
Pra finalizar vou adicionar 5 métodos no CargoType, assim não precisarei mais fazer essas comparações de getCargo() com o Enumerado. Vou criar os métodos isOperador(), isSupervisor(), isGerente(), isDiretor() e isAdministrador() no CargoType.  Segue a implementação:
CargoType.java: 
/* CODIGO ANTERIOR OMITIDO */

public boolean isOperador() {
return this == OPERADOR;
}

public boolean isSupervisor() {
return this == SUPERVISOR;
}

public boolean isGerente() {
return this == GERENTE;
}

public boolean isDiretor() {
return this == DIRETOR;
}

public boolean isAdministrador() {
return this == ADMINISTRADOR;
}
/* CODIGO POSTERIOR OMITIDO */
Agora é só substituir em todos os fontes que faziam a comparação.

Conclusão
Nesse post fiz algumas correções e melhorias na aplicação. Nos próximos posts vou adicionar mais recursos do BPM.

Segue o link dessa video aula: https://youtu.be/A-X4pJwvvA8

Até mais,


Nenhum comentário:

Postar um comentário

Versão 23.3.0-Final

      Introdução Nesse post vou mostrar as principais novidades da versão 23.3.0, algumas correções e pequenas alterações. Alterações Além d...