Pragiva — Tecnologia na prática

Testando a tabela criada: a primeira tela de cadastro

Tela de cadastro MVC para testar a tabela criada: o que conferir na primeira inclusão — código sugerido, gatilho, combo, checkbox, memo e pastas.

Protheus Tutorial 6 min de leitura

Assista o vídeo

Nesta página5 seções

Antes de começar

  • A tabela ZA1 criada no Configurador, com os campos, os índices, o gatilho de idade, as pastas e os agrupamentos dos artigos anteriores da série.
  • As funções U_ZA1NUM() (inicializador do código) e U_ZA1VldIdade() (validação do nascimento), dos artigos anteriores, compiladas no mesmo repositório.
  • Um ambiente de desenvolvimento onde você possa compilar fontes no repositório.
  • Acesso ao Configurador para pôr a rotina no menu de um módulo.

Tabela criada, campos configurados, índice e gatilho no lugar — e nada disso aparece para ninguém até existir uma rotina que abra a tabela. O dicionário descreve; quem mostra é uma tela. Este texto entrega a tela mínima para a ZA1, o cadastro de motoristas desta série, e diz o que conferir nela para saber se o que foi configurado no Configurador está funcionando.

A tela é MVC. O motivo prático: FWFormStruct lê o dicionário e monta a estrutura sozinha, então tudo o que você configurou — título, tipo, combo, validação, inicializador, pasta, gatilho — chega à tela sem uma linha a mais de código. Se MVC é novidade, comece por MVC no Protheus: o que é e por que existe.

O que a primeira inclusão tem de mostrar

Este é o plano de teste. Quando a rotina estiver no menu, clique em Incluir e confira cada linha abaixo; cada uma testa uma configuração feita num artigo anterior. Se um item falhar, o problema não está no fonte da próxima seção, que não sabe nada sobre esses campos: está no dicionário ou numa das duas funções que ele chama, U_ZA1NUM() e U_ZA1VldIdade() — confira se ambas estão compiladas no repositório.

O que ver na telaO que isso comprovaOnde foi configurado
Código já preenchidoO inicializador U_ZA1NUM(), que só pede número na inclusãoCampo caractere
Nome vazio é recusadoA obrigatoriedade do nome, marcada na pasta Uso em Campo caractere e cobrada ao confirmar, e o NaoVazio() da validação do campoValidação
Idade calculada sozinhaO gatilho ZA1_NASC → ZA1_IDADE, com um nascimento que U_ZA1VldIdade() aceiteGatilhos
Vínculo em listaO combo 1=Proprio;2=Agregado;3=TerceiroCampo combo
MOPP é caixa de marcarO campo lógicoCampo lógico
Observação multilinhaO campo memo, área de textoCampo memo
Campos em duas pastasAs pastas Dados do motorista e ObservacoesPastas
Separador IdentificacaoO agrupamento A01: ZA1_COD, ZA1_NOME, ZA1_NASC e ZA1_IDADE sob um títuloAgrupamentos
Painel Vinculo e MOPPO agrupamento A02: ZA1_VINC e ZA1_MOPP, que podem ser escondidos e reveladosAgrupamentos

Se uma linha falhar, confira no dicionário:

  • Código já preenchido: X3_RELACAO do ZA1_COD.
  • Nome vazio é recusado: o obrigatório na pasta Uso do Configurador; X3_VALID e X3_VLDUSER do ZA1_NOME.
  • Idade calculada sozinha: X3_TRIGGER do ZA1_NASC e a regra na SX7.
  • Vínculo em lista: X3_CBOX do ZA1_VINC.
  • MOPP é caixa de marcar: X3_TIPO do ZA1_MOPP = L.
  • Observação multilinha: X3_TIPO do ZA1_OBS = M.
  • Campos em duas pastas: X3_FOLDER de cada campo e as pastas na SXA.
  • Separador Identificacao: X3_AGRUP = A01 nos quatro campos; XA_TIPO = 2 na SXA.
  • Painel Vinculo e MOPP: X3_AGRUP = A02 nos dois campos; XA_TIPO = 1 na SXA.

A consulta ao fim do texto traz essas colunas da SX3; as da SXA estão na consulta de pastas e agrupamentos.

O fonte

Para chegar a essa tela basta o mesmo molde do cadastro didático publicado em Seu primeiro cadastro MVC, do dicionário à tela, trocando a tabela e os nomes: função principal com o browse, e as três Static Function que o framework procura pelo nome.

ZA1CAD.prwADVPL / TLPP
#Include "Protheus.ch"
#Include "FWMVCDef.ch"

/*/{Protheus.doc} ZA1CAD
Cadastro de motoristas (tabela customizada ZA1) em MVC, entidade unica.

Toda a tela vem do dicionario: FWFormStruct le a SX3 da ZA1 e traz
titulos, tipos, combos, validacoes, inicializadores, pastas e gatilhos.
Nao ha gravacao no fonte: o MPFormModel instala o commit padrao.

Exemplo didatico. Crie a tabela ZA1 no Configurador antes de compilar.

@type user function
@return nil
@example U_ZA1CAD()
/*/
User Function ZA1CAD()

    Local oBrowse := Nil

    oBrowse := FWMBrowse():New()
    oBrowse:SetAlias("ZA1")
    oBrowse:SetDescription("Motoristas")

    // Nome do FONTE onde esta o MenuDef, nao o nome da funcao.
    oBrowse:SetMenuDef("ZA1CAD")

    oBrowse:Activate()

Return Nil

/*/{Protheus.doc} MenuDef
Opcoes do browse. As de edicao apontam todas para VIEWDEF.ZA1CAD; o
OPERATION e que distingue incluir, alterar e excluir.
@type static function
@return array, o aRotina do browse
/*/
Static Function MenuDef()

    Local aRotina := {}

    ADD OPTION aRotina TITLE "Pesquisar"  ACTION "AxPesqui"       OPERATION 1 ACCESS 0
    ADD OPTION aRotina TITLE "Visualizar" ACTION "VIEWDEF.ZA1CAD" OPERATION 2 ACCESS 0
    ADD OPTION aRotina TITLE "Incluir"    ACTION "VIEWDEF.ZA1CAD" OPERATION 3 ACCESS 0
    ADD OPTION aRotina TITLE "Alterar"    ACTION "VIEWDEF.ZA1CAD" OPERATION 4 ACCESS 0
    ADD OPTION aRotina TITLE "Excluir"    ACTION "VIEWDEF.ZA1CAD" OPERATION 5 ACCESS 0

Return aRotina

/*/{Protheus.doc} ModelDef
O modelo: estrutura lida do dicionario e chave primaria.
@type static function
@return object, o modelo de dados
/*/
Static Function ModelDef()

    Local oModel  := Nil

    // 1 = estrutura do MODELO, a partir da SX3.
    Local oStruct := FWFormStruct(1, "ZA1")

    // O ID do modelo e diferente do nome da funcao principal.
    oModel := MPFormModel():New("ZA1CADM")

    oModel:AddFields("ZA1MASTER", /*cOwner*/, oStruct)

    oModel:SetDescription("Motoristas")
    oModel:GetModel("ZA1MASTER"):SetDescription("Dados do motorista")

    // Mesma chave do indice 1 da ZA1.
    oModel:SetPrimaryKey({"ZA1_FILIAL", "ZA1_COD"})

Return oModel

/*/{Protheus.doc} ViewDef
A tela: recebe o modelo e diz onde cada componente aparece.
@type static function
@return object, a view ligada ao modelo
/*/
Static Function ViewDef()

    Local oView   := Nil
    Local oModel  := FWLoadModel("ZA1CAD")

    // 2 = estrutura da VIEW. As pastas da SXA vem junto.
    Local oStruct := FWFormStruct(2, "ZA1")

    oView := FWFormView():New()
    oView:SetModel(oModel)

    oView:AddField("VIEW_ZA1", oStruct, "ZA1MASTER")

    oView:CreateHorizontalBox("TELA", 100)

    // Sem SetOwnerView o componente existe e nao aparece.
    oView:SetOwnerView("VIEW_ZA1", "TELA")

Return oView

O fonte segue linha a linha o molde publicado; não foi compilado para este texto. As regras que valem para ele são as mesmas de lá, e cada uma tem artigo próprio:

  • SetMenuDef("ZA1CAD") e FWLoadModel("ZA1CAD") recebem o nome do fonte — por isso o fonte precisa se chamar ZA1CAD (MenuDef).
  • FWFormStruct(1, ...) vai para o modelo, FWFormStruct(2, ...) para a tela; trocar os dois é erro de tipo em tempo de execução (ModelDef, ViewDef).
  • SetPrimaryKey recebe a mesma chave do índice 1 da ZA1, ZA1_FILIAL+ZA1_COD (Índices no Protheus).

Compilar e chamar

Compile o fonte ZA1CAD no repositório do ambiente de desenvolvimento (Compilar AdvPL e TLPP pela linha de comando). Depois ponha U_ZA1CAD no menu do módulo, como função de usuário — o passo a passo, com o grupo Customizados no Faturamento, está em Menus do Protheus.

A rotina abre um browse vazio, com as opções do MenuDef.

A primeira inclusão

Clique em Incluir e percorra a tabela do plano de teste, no início do texto.

Dois cuidados nessa conferência:

A idade precisa mudar com o nascimento. Informe uma data, veja a idade; troque a data, veja a idade mudar. Use datas que atendam a idade mínima do parâmetro MV_XIDMIN, lido pela U_ZA1VldIdade(): uma data abaixo dela é recusada com a mensagem da validação, e a idade não aparece — isso é a regra funcionando, não o gatilho falhando (Validação). Para saber qual idade mínima vale no seu ambiente:

Confira no seu ambienteSQL
SELECT X6_FIL, X6_VAR, X6_TIPO, X6_DESCRIC, X6_CONTEUD
  FROM SX6010
 WHERE X6_VAR = 'MV_XIDMIN'
   AND D_E_L_E_T_ = ' '

Sem linha, o parâmetro não foi criado e a função usa o 21 do fonte. Se a data foi aceita e a idade não aparece, o gatilho não disparou — a consulta à SX7 do artigo de gatilhos mostra se ele existe e com qual condição. Se aparece errada perto do aniversário, a regra está fazendo conta de dias em vez de usar DateDiffYear().

Dois “Outros” diferentes. O primeiro é a aba Outros, das pastas. Bloqueio (ZA1_MSBLQL) e foto (ZA1_BITMAP) não foram distribuídos em Dados do motorista nem em Observacoes. Campo sem pasta reconhecida aparece em Outros — é inclusive o sintoma que a Central de Atendimento descreve quando a SXA de uma tabela não é reconhecida e o cadastro inteiro cai nessa aba (Pastas e agrupamentos). Se o bloqueio não estiver lá, confira o nível: o _MSBLQL criado pelo Configurador nasce com nível 9, visível apenas para o Administrador, e um usuário comum só o vê depois de ajustado o nível de cada módulo (Campos reservados). O segundo é dos agrupamentos: segundo a TDN, os campos que não estiverem em nenhum agrupamento aparecem listados num separador chamado Outros. Um é aba (pasta), o outro é separador (agrupamento); não confunda um com o outro ao conferir onde cada campo foi parar.

Depois de gravar, abra a alteração do mesmo registro e confira o nascimento: ele foi configurado para ser editável só na inclusão (Modo de edição). Se você adotou uma das variantes daquele artigo que liberam a correção na alteração — para administradores ou para usuários autorizados —, quem está nesses grupos continua editando o campo. Faça esse teste com um usuário comum.

Confira no banco

O registro gravado, lido direto da tabela física:

Confira no seu ambienteSQL
SELECT ZA1_FILIAL, ZA1_COD, ZA1_NOME, ZA1_NASC, ZA1_IDADE, ZA1_VINC, ZA1_MOPP
  FROM ZA1010
 WHERE D_E_L_E_T_ = ' '
 ORDER BY ZA1_COD

O sufixo 010 é o da empresa; troque pelo do seu ambiente. ZA1_NASC volta como texto AAAAMMDD (Campo data), e a observação, por ser memo, não se lê direto por essa consulta.

Se a consulta não devolve nada depois de uma inclusão que a tela aceitou, ou se a tabela física nem existe, comece conferindo o dicionário:

Confira no seu ambienteSQL
SELECT X3_CAMPO, X3_TIPO, X3_TAMANHO, X3_TITULO, X3_RELACAO, X3_VALID,
       X3_VLDUSER, X3_CBOX, X3_TRIGGER, X3_FOLDER, X3_AGRUP
  FROM SX3010
 WHERE X3_ARQUIVO = 'ZA1'
   AND D_E_L_E_T_ = ' '
 ORDER BY X3_ORDEM

Campo que falta aqui não existe na tela, no modelo nem no banco — e nenhum ajuste no ZA1CAD resolve isso. As mesmas colunas diagnosticam as linhas do plano de teste; pastas e agrupamentos se completam com a consulta à SXA.

Se a sua primeira tela abre e algum desses itens não bate, fale com a gente.

Referências

  1. TDNtdn.totvs.com

    TDN — AdvPl utilizando MVC
  2. TDNtdn.totvs.com

    TDN — MPFormModelGrava os dados pelo dicionário; o bloco bCommit tem como padrão FWFormCommit.
  3. TDNtdn.totvs.com

    TDN — FWFormStructEstrutura de metadado do dicionário para Model e View: tipo 1 para o modelo, 2 para a view.
  4. TDNtdn.totvs.com

    TDN — Comportamento de gatilhos em MVCO MVC executa as validações e os gatilhos dos campos envolvidos na regra.
  5. TDNtdn.totvs.com

    TDN — SXA, Pastas e Agrupamentos de camposPastas da SXA num FormField de rotina MVC.
  6. TDNtdn.totvs.com

    TDN — Painel e Separador em rotinas MVCSeparador define título; Painel permite esconder e revelar campos. Campos fora de agrupamento aparecem listados num Separador chamado Outros.
  7. Central de Atendimentocentraldeatendimento.totvs.com

    Central de Atendimento TOTVS — Cadastro de cliente só apresenta a aba OutrosCampos sem pasta reconhecida na SXA aparecem na aba Outros.

Continue por aqui