Módulos do guia

Nível 2 · Consulta e relatórios · Módulo 08

Consulta e navegação

Duração estimada: 2h a 3h

Você vai sair sabendo

  • →Criar uma Info Window para buscar visitas
  • →Tirar os textos do código e colocá-los em mensagens traduzíveis
  • →Tornar uma regra configurável por empresa, com o System Configurator
  • →Criar índices pelo Dicionário, para que viajem no 2Pack
  • →Mostrar informação de contexto numa linha de status
  • →Ligar e consultar o histórico de alterações de uma tabela

Checkpoint: 0 de 7

ver .md

Antes de começar

  • Módulo 07 concluído, com visitas de vários clientes e técnicos no banco.
  • Este módulo é quase todo Dicionário. O Java aparece só no passo 3, para usar mensagens e configuração.

O que você vai construir

Com dezenas de visitas, a janela Visita Técnica deixa de ser o melhor jeito de encontrar alguma coisa. Neste módulo, você cuida de quem consulta:

  • Uma Info Window: busca rápida de visitas, com filtros, que também serve de lookup.
  • Mensagens no Dicionário: os erros do plugin passam a ser traduzíveis e editáveis sem recompilar.
  • Uma configuração para a regra "visita concluída precisa de linha", que cada empresa pode ligar ou desligar.
  • Um índice para as consultas que o plugin faz o tempo todo.
  • Uma linha de status no cadastro do cliente: "3 visitas técnicas em aberto".
  • O histórico de alterações das visitas.

Passo a passo

1. A Info Window

Conceito: uma Info Window é uma tela de busca: filtros em cima, resultado em grade embaixo. Não edita nada. Serve para o usuário encontrar registros e, a partir deles, abrir a janela ou rodar um processo.

Como System, na janela Info Window, crie:

CampoValor
NameVisitas Técnicas
TableEDU_Visita
Sql FROMEDU_Visita v INNER JOIN C_BPartner bp ON (bp.C_BPartner_ID=v.C_BPartner_ID)
Sql ORDER BYv.EDU_DataVisita DESC
Entity TypeEDU
WindowVisita Técnica
Defaultmarcado

O campo Window é o destino do zoom: o duplo clique numa linha abre a visita nessa janela. Default faz desta a Info Window padrão da tabela EDU_Visita.

Na aba Column, crie as colunas. Sql SELECT é a expressão, com o alias do FROM; Query Criteria marca as que viram filtro:

SeqNameDB Column NameSql SELECTReferenceQuery CriteriaDetalhes
10VisitaEDU_Visita_IDv.EDU_Visita_IDIDKey column marcado, Displayed desmarcado
20DataEDU_DataVisitav.EDU_DataVisitaDatesimRange marcado
30ClienteC_BPartner_IDv.C_BPartner_IDSearchsimOperador =
40Nome do clienteNamebp.NameStringsimOperador Full Like
50TécnicoSalesRep_IDv.SalesRep_IDTablesimReference Key: AD_User - Internal
60TipoEDU_TipoVisitav.EDU_TipoVisitaListsimReference Key: EDU_TipoVisita
70ConcluídaEDU_IsConcluidav.EDU_IsConcluidaYes-NosimOperador =

Salve e clique em Validate, na aba Window. O iDempiere monta o SQL e testa no banco; se estiver certo, marca Valid. Uma Info Window inválida não abre.

Crie a entrada de menu com Action Info e Info Window Visitas Técnicas, e rode Role Access Update como GardenAdmin.

Teste como GardenAdmin: busque as visitas em aberto de um cliente, depois as de um técnico no mês. Dê duplo clique numa linha: a visita abre na janela.

2. Mensagens no Dicionário

Hoje o plugin tem dois textos em português escritos no Java. Isso tem três problemas: não dá para traduzir, não dá para corrigir sem recompilar e ninguém encontra o texto procurando no Dicionário.

Na janela Message, crie:

Search KeyMessage TypeMessage Text
EDU_VisitaSemLinhasErrorInclua pelo menos uma linha antes de concluir a visita.
EDU_ClienteComVisitaAbertaErrorEste cliente tem visitas técnicas em aberto. Conclua as visitas antes de desativá-lo.
EDU_VisitasEmAbertoInformationVisitas técnicas em aberto: {0}

Entity Type EDU em todas. A terceira é para o passo 5. O {0} é um marcador do MessageFormat do Java.

3. Uma regra configurável

Conceito: o System Configurator guarda parâmetros que mudam o comportamento do sistema sem mexer no código. Cada parâmetro tem um nível: pode valer para o sistema todo, ou ser sobrescrito por empresa ou por organização.

Na janela System Configurator, crie:

CampoValor
NameEDU_VISITA_EXIGE_LINHA
DescriptionY: só conclui visita com pelo menos uma linha. N: permite concluir sem linhas.
Configured ValueY
Configuration LevelClient
Entity TypeEDU

Com o nível Client, a GardenWorld pode ter o próprio registro com outro valor, e ele vale só para ela.

Agora o Java. Na MVisita, troque a regra de conclusão:

public static final String SYSCONFIG_EXIGE_LINHA = "EDU_VISITA_EXIGE_LINHA";

@Override
protected boolean beforeSave(boolean newRecord) {
    if (getC_BPartner_Location_ID() <= 0
            || is_ValueChanged(COLUMNNAME_C_BPartner_ID) && !is_ValueChanged(COLUMNNAME_C_BPartner_Location_ID)) {
        setC_BPartner_Location_ID(getEnderecoPadrao(getCtx(), getC_BPartner_ID(), get_TrxName()));
    }

    if (isEDU_IsConcluida()
            && is_ValueChanged(COLUMNNAME_EDU_IsConcluida)
            && MSysConfig.getBooleanValue(SYSCONFIG_EXIGE_LINHA, true, getAD_Client_ID())
            && getLinhas().isEmpty()) {
        log.saveError("Error", Msg.getMsg(getCtx(), "EDU_VisitaSemLinhas"));
        return false;
    }
    return true;
}

Imports: org.compiere.model.MSysConfig e org.compiere.util.Msg.

E no ClienteComVisitaAberta, do módulo 05:

if (temVisitaAberta)
    throw new AdempiereException(Msg.getMsg(cliente.getCtx(), "EDU_ClienteComVisitaAberta"));

Dois detalhes:

  • O valor padrão do getBooleanValue é true: se alguém apagar a configuração, a regra continua valendo. Escolha o padrão mais seguro.
  • O nome da configuração vira constante. Ele é usado no código e digitado no Dicionário; uma constante evita que os dois se desencontrem.

Reinicie o servidor e teste: com Y, a regra funciona como antes. Mude o valor para N, conclua uma visita sem linhas e veja passar. O valor é lido em cache: se a mudança não aparecer, use Cache Reset no menu. Volte para Y no fim.

4. Índices pelo Dicionário

O plugin consulta visitas por cliente e situação em três lugares: o event handler do módulo 05, o processo do módulo 06 e a linha de status do próximo passo. Com poucas visitas, tanto faz. Com cem mil, é a diferença entre instantâneo e travado.

Como System, na janela Table and Column, tabela EDU_Visita, aba Table Index:

CampoValor
NameEDU_Visita_Cliente
Uniquedesmarcado
Entity TypeEDU

Na aba Index Column:

SequenceColumn
10C_BPartner_ID
20EDU_IsConcluida

Volte à aba Table Index e clique em Index Validate. Confira no psql:

\d edu_visita

Pelo Dicionário, e não com CREATE INDEX direto no banco, pelo mesmo motivo da view do módulo 07: o índice vai no 2Pack junto com a tabela.

5. A linha de status no cliente

Conceito: uma Status Line executa uma consulta e mostra o resultado formatado por uma mensagem. Pode aparecer na barra de status de uma janela ou no painel de ajuda ao lado.

Na janela Status Line, crie:

CampoValor
NameEDU Visitas em aberto do cliente
MessageEDU_VisitasEmAberto
SQL Expression/StatementSELECT COUNT(*) FROM EDU_Visita WHERE C_BPartner_ID=@C_BPartner_ID@ AND EDU_IsConcluida='N' AND IsActive='Y'
Entity TypeEDU

Na aba Used In:

CampoValor
WindowBusiness Partner
TabBusiness Partner
Status Linemarcado

O @C_BPartner_ID@ é lido do contexto da janela, como nas lógicas do módulo 02. O resultado entra no lugar do {0} da mensagem.

Teste como GardenAdmin: abra Business Partner, navegue até um cliente com visitas e veja a contagem na barra de status. Mude de cliente e ela muda junto.

6. Histórico de alterações

Conceito: o iDempiere pode registrar cada mudança de valor, com usuário, data, valor antigo e novo. Vem desligado por padrão, tabela por tabela, porque ocupa espaço.

Na tabela EDU_Visita, marque Maintain Change Log e salve.

Como GardenAdmin:

  1. Abra uma visita, mude o Tipo e salve.
  2. Clique com o botão direito no campo Tipo e escolha Change Log. Aparece a mudança, com quem fez e quando.
  3. Para ver tudo o que mudou no sistema, use a janela Change Audit.

7. Commit

Inclua no Pack Out a Info Window (tipo Info Window), as três mensagens (tipo Message) e o item de menu. A tabela EDU_Visita entra de novo, porque ganhou índice e Maintain Change Log.

A Status Line e a configuração não têm tipo próprio: vão como Data, com a tabela e uma consulta em SQL Expression/Statement:

TypeTableSQL Expression/Statement
DataAD_StatusLineSELECT * FROM AD_StatusLine WHERE EntityType='EDU'
DataAD_StatusLineUsedInSELECT * FROM AD_StatusLineUsedIn WHERE EntityType='EDU'
DataAD_SysConfigSELECT * FROM AD_SysConfig WHERE Name='EDU_VISITA_EXIGE_LINHA'

Gere o 2Pack_1.0.4.zip.

git add .
git commit -m "Visitas 1.0.4: info window, mensagens, configuração, índice, status line e change log"

Checkpoint

0 de 7 itens

Erros comuns

SintomaCausa provávelCorreção
A Info Window não abre, ou não aparece no menuValid desmarcado, ou faltou Role Access UpdateClique em Validate e leia o erro; rode o processo de acesso
Validate acusa erro de SQLAlias do Sql SELECT diferente do Sql FROMUse v. e bp. como no FROM
Duplo clique não abre a visitaFaltou Window na Info Window ou Key column na coluna do IDPasso 1
A mensagem aparece como EDU_VisitaSemLinhasA mensagem não existe ou a Search Key está diferenteConfira a Search Key, letra por letra
Mudei a configuração e nada aconteceuValor em cacheCache Reset
Index Validate falhaNome de índice já existe ou coluna erradaConfira no \d edu_visita
A linha de status não apareceStatus Line desmarcado em Used In, ou Window/Tab erradosPasso 5
Não aparece Change Log no botão direitoPerfil sem Show Change Log, ou tabela sem Maintain Change LogPasso 6

Desafio

Adicione à Info Window um processo: Gerar Visitas de Manutenção (módulo 06), na aba Process da Info Window. Depois, faça a linha de status mostrar também a data da próxima visita em aberto do cliente (dica: {1} na mensagem e uma segunda coluna no SELECT).

Referência

Níveis do System Configurator

Configuration LevelQuem pode sobrescrever
SystemNinguém: vale o registro do System
ClientCada empresa, com um registro próprio
OrganizationCada organização, com um registro próprio

No código, o método recebe o nível mais específico que você conhece: getBooleanValue(nome, padrão), getBooleanValue(nome, padrão, AD_Client_ID) ou getBooleanValue(nome, padrão, AD_Client_ID, AD_Org_ID). Existem as mesmas variações para getValue, getIntValue e getBigDecimalValue.

Mensagens no código

SituaçãoComo
Texto simplesMsg.getMsg(ctx, "Chave")
Com valoresMsg.getMsg(ctx, "Chave", new Object[] {valor}), com {0}, {1} na mensagem
Em exceçãonew AdempiereException("@Chave@"): o texto entre arrobas é traduzido ao exibir
Em beforeSavelog.saveError("Error", Msg.getMsg(getCtx(), "Chave"))

Operadores da Info Column

=, !=, >, >=, <, <=, Like (começa com) e Full Like (contém). Para ignorar maiúsculas, use UPPER(bp.Name) no Sql SELECT. Colunas com Range pedem "de" e "até".

Próximo módulo

09 · Documentos e aprovação: a visita vira um documento, com número, status, completar, anular e aprovação.