terça-feira, 25 de agosto de 2020

Contas Pagar/Receber - Parte XXVIII - Pequenos Ajustes e Refatorações

Introdução
Nesse vigésimo oitavo post vou fazer algumas refatorações e pequenos ajustes na aplicação

Correção Aprovação
Nossa aplicação está ocorrendo um erro quando uma conta é aprovada, esse problema está ocorrendo porque utilizei o momento errado de interceptar o evento da ação dinâmica. No LancamentoObserver existe o seguinte método:
LancamentoObserver.java:

private void avaliacao(@Observes @JArchEventDynamicBefore(Constant.ID_AVALIAR_LANCAMENTO)                      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()));
}
Vou alterar o @JArchEventDynamicBefore para @JArchEventDynamicAfter:

private void avaliacao(@Observes @JArchEventDynamicAfter(Constant.ID_AVALIAR_LANCAMENTO)                      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()));
}
Ordem Download Comprovante
Na tela de lista de lançamentos o atributo order está setado como 3 conflitando com o a ação dinâmica de avaliar conta, vou alterar o valor para 4:
LancamentoListAction.java:

@JArchDynamicDownload(id = "idDownloadComprovanteBaixa", labelMenu = "label.comprovanteBaixa", 
    order = 4, elDisabled = "#{(l -> l.aberto)(lancamento)}")
public StreamedContent downloadComprovanteBaixa(LancamentoEntity lancamento) {
return getFacade().downloadComprovanteBaixa(lancamento);
}
Refatoração init() do LancamentoListAction
O método init() no LancamentoListAction apesar de bem escrito e legível podemos melhorar usa leitura refatorando em pequenos métodos. Atualmente o método está implementado da seguinte maneira:
LancamentoListAction.java:

@PostConstruct
private void init() {
if (isStartedWorkFlow()) {
Long idLancamento = Long.valueOf(getTask().get().getBusinessKey());
LancamentoEntity lancamento = getFacade().find(idLancamento);
tipoLancamento = lancamento.getTipoLancamento();
callActionDynamic(idLancamento, Constant.ID_AVALIAR_LANCAMENTO);
return;
}

deactiveWhereJpa(LancamentoEntity.FILTRO_VENCIDO);
deactiveWhereJpa(LancamentoEntity.FILTRO_VENCENDO);
deactiveWhereJpa(LancamentoEntity.FILTRO_ID);

tipoLancamento = TipoLancamentoType.valueOf(JsfUtils.getParameterRequest("tipo"));
activeAndAddParamWhereJpa(LancamentoEntity.FILTRO_TIPO_LANCAMENTO, "tipoLancamento", tipoLancamento);

String statusParam = JsfUtils.getParameterRequest("status");
if (statusParam != null) {
StatusLancamentoType status = StatusLancamentoType.valueOf(statusParam);
if (StatusLancamentoType.VENCIDO.equals(status)) {
activeAndAddParamWhereJpa(LancamentoEntity.FILTRO_VENCIDO, "dataSistema", LocalDate.now());
} else if (StatusLancamentoType.VENCENDO.equals(status)) {
activeAndAddParamWhereJpa(LancamentoEntity.FILTRO_VENCENDO, "dataSistema", LocalDate.now());
}
}

String id = JsfUtils.getParameterRequest("id");
if (id != null) {
activeAndAddParamWhereJpa(LancamentoEntity.FILTRO_ID, "id", Long.valueOf(id));
}

if (!parametroUtilizaPessoa.getValue()) {
getColumnDataTable("pessoa.nome").ifPresent(c -> c.hide());
}

getFieldSearch("vencimentoInicio").ifPresent(f -> f.disabledCondition(true));
getFieldSearch("vencimentoFim").ifPresent(f -> f.disabledCondition(true));
getFieldSearch("valorInicio").ifPresent(f -> f.disabledCondition(true));
getFieldSearch("valorFim").ifPresent(f -> f.disabledCondition(true));
}
Vou começar refatorando pelo primeiro IF onde verificar se a chamada foi feito via lista de tarefa (BPM).
@PostConstruct
private void init() {
if (isStartedWorkFlow()) {
chamaAvalicaoConta();
return;
}

private void chamaAvalicaoConta() {
Long idLancamento = Long.valueOf(getTask().get().getBusinessKey());
LancamentoEntity lancamento = getFacade().find(idLancamento);
tipoLancamento = lancamento.getTipoLancamento();
callActionDynamic(idLancamento, Constant.ID_AVALIAR_LANCAMENTO);
}
Agora vou refatorar também onde está limpando os filtros:
@PostConstruct
private void init() {
if (isStartedWorkFlow()) {
chamaAvalicaoConta();
return;
}

limpaFiltros();

private void limpaFiltros() {
deactiveWhereJpa(LancamentoEntity.FILTRO_VENCIDO);
deactiveWhereJpa(LancamentoEntity.FILTRO_VENCENDO);
deactiveWhereJpa(LancamentoEntity.FILTRO_ID);
}
Agora vou ajustar o filtro de tipo de lancamento:
@PostConstruct
private void init() {
if (isStartedWorkFlow()) {
chamaAvalicaoConta();
return;
}

limpaFiltros();

configuraFiltroTipoLancamento();

private void configuraFiltroTipoLancamento() {
tipoLancamento = TipoLancamentoType.valueOf(JsfUtils.getParameterRequest("tipo"));
activeAndAddParamWhereJpa(LancamentoEntity.FILTRO_TIPO_LANCAMENTO, "tipoLancamento", tipoLancamento);
}
Agora vou ajustar o filtro de status:
@PostConstruct
private void init() {
if (isStartedWorkFlow()) {
chamaAvalicaoConta();
return;
}

limpaFiltros();

configuraFiltroTipoLancamento();

configuraFiltroStatus();

private void configuraFiltroStatus() {
String statusParam = JsfUtils.getParameterRequest("status");
if (statusParam != null) {
StatusLancamentoType status = StatusLancamentoType.valueOf(statusParam);
if (StatusLancamentoType.VENCIDO.equals(status)) {
activeAndAddParamWhereJpa(LancamentoEntity.FILTRO_VENCIDO, "dataSistema", LocalDate.now());
} else if (StatusLancamentoType.VENCENDO.equals(status)) {
activeAndAddParamWhereJpa(LancamentoEntity.FILTRO_VENCENDO, "dataSistema", LocalDate.now());
}
}
}
Agora o filtro por ID:
@PostConstruct
private void init() {
if (isStartedWorkFlow()) {
chamaAvalicaoConta();
return;
}

limpaFiltros();

configuraFiltroTipoLancamento();

configuraFiltroStatus();

configuraFiltroId();
private void configuraFiltroId() {
String id = JsfUtils.getParameterRequest("id");
if (id != null) {
activeAndAddParamWhereJpa(LancamentoEntity.FILTRO_ID, "id", Long.valueOf(id));
}
}
Agora configuração de visualização da coluna nome da pessoa no datatable:
@PostConstruct
private void init() {
if (isStartedWorkFlow()) {
chamaAvalicaoConta();
return;
}

limpaFiltros();

configuraFiltroTipoLancamento();

configuraFiltroStatus();

configuraFiltroId();

configuraVisualizacaoColunaPessoa();
private void configuraVisualizacaoColunaPessoa() {
if (!parametroUtilizaPessoa.getValue()) {
getColumnDataTable("pessoa.nome").ifPresent(c -> c.hide());
}
}
E por último o bloqueio das condições de datas e valores na div de pesquisa:
@PostConstruct
private void init() {
if (isStartedWorkFlow()) {
chamaAvalicaoConta();
return;
}

limpaFiltros();

configuraFiltroTipoLancamento();

configuraFiltroStatus();

configuraFiltroId();

configuraVisualizacaoColunaPessoa();

desabilitaCondicaoIntervalo();
}
private void desabilitaCondicaoIntervalo() {
getFieldSearch("vencimentoInicio").ifPresent(f -> f.disabledCondition(true));
getFieldSearch("vencimentoFim").ifPresent(f -> f.disabledCondition(true));
getFieldSearch("valorInicio").ifPresent(f -> f.disabledCondition(true));
getFieldSearch("valorFim").ifPresent(f -> f.disabledCondition(true));
}
Conclusão
Nesse post fiz algumas melhorias no código. Melhorias no código devem ser frequentemente aplicadas, principamente quando o código sofre constantes alterações ou implementações. Uma boa prática de programação é sempre manter o código mais simples possível, ser auto documentado, utilização de boas práticas de programação orientada a objetos, buscando sempre a coesão e desacoplamento.

Segue o link dessa video aula: https://youtu.be/pSWQI6Qka3c

Até mais,

quinta-feira, 6 de agosto de 2020

Contas Pagar/Receber - Parte XXVII - Eliminando Task Chamar Atenção

Introdução
Nesse vigésimo sétimo post vou fazer que a Task de Chamar Atenção (Supervisor e Gerente) deixe de existir quando o usuário (Supervisor ou Gerente) finalizar a Task de avaliação. 

Task Chamar Atenção
Nas tarefas de Avaliar Conta tanto do Supervisor quanto do Gerente existe uma evento de borda de Timer que gera uma Task de Chamar Atenção caso o prazo estipulado seja atingido. Atualmente deixei configurado como 5 minutos, caso o usuário responsável pela Task não finalize dentro do prazo é gerado uma Task para seu superior lhe chamar a atenção. Depois que essa Task de Chamar Atenção é criada, mesmo o usuário finalizando a Task de Avaliar Conta, a Task de Chamar Atenção ainda continua existindo na lista de tarefas do seu superior. Para resolver isso vou criar um outro evento de borda para que quando a variável de aprovação for adicionada ao fluxo essa tarefa deixa de existir. Vou fazer essa implementação primeiro na Task de Chamar Atenção Supervisor:
  

Repare que utilizei o componente Conditional Boundary, preenchi o campo Variable Name com aprovadoSupervisor, Condition Type como Expression e Expression com a EL #{aprovadoSupervisor ne null}. 
Agora vou fazer a mesma coisa com a task Chamar Atenção Gerente:

Executei o mesmo procedimento, somente alterando o nome da variável de aprovadoSupervisor para aprovadoGerente.

Com essa implementação, agora mesmo após a criação da tarefa de Chamar Atenção, quando o usuário finalizar a tarefa de Avaliar Conta a Task de Chamar Atenção vai deixar de existir.

Conclusão
Nesse post eu utilizei o evento de borda de condição para eliminar a Task de Chamar Atenção quando o usuário finalizar a avaliação da conta.

Segue o link dessa video aula: https://youtu.be/p_XejiN_lF4

Até mais,

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...