Função para cadastro de SX5

Olá pessoal…

Hoje vou mostrar um exemplo que fiz, de função para cadastro de dados em uma tabela genérica – SX5.


O intuito da rotina, é liberar o cadastro de informações nas tabelas genéricas para um usuário comum, que se fosse uma pequena AxCadastro de manipulação dos dados.

Para utilizar a rotina, basta passar por parâmetro qual é a tabela genérica e o título da rotina.

Ao executar, é mostrado uma grid com os registros da tabela genérica.

Grid com os dados de uma tabela genérica - SX5

Grid com os dados de uma tabela genérica – SX5

Ao clicar em Incluir, Alterar, etc é mostrado a tela, porém sem o campo de Tabela, apenas a Chave e os dados, e a Chave liberada apenas na Inclusão.

Edição de um registro

Edição de um registro

Fonte Novo (2024)


Foi atualizado o fonte, dando uma modernizada nos comandos.

Abaixo segue o código:

//Bibliotecas
#Include "Totvs.ch"
#Include "FWMVCDef.ch"

//Variveis Estaticas
Static cTitulo := "Tabelas Genéricas"
Static cAliasMVC := "SX5"

/*/{Protheus.doc} User Function zCadSX5
Cadastro de Tabela Genérica
@author Atilio
@since 15/02/2024
@version 1.0
@type function
@example
	u_zCadSX5("01", "Séries de NF")
/*/

User Function zCadSX5(cTabela, cTitTela)
	Local aArea      := FWGetArea()
	Local oBrowse
    Local aInfoCab   := {}
    Local aColunas   := {}
	Private aRotina  := {}
    Private cTabGen  := ""
    Default cTabela  := ""
    Default cTitTela := ""

    //Somente se tiver tabela
    If ! Empty(cTabela)
        //Atualiza a tabela em uso e o título
        cTabGen := cTabela
        cTitulo := cTitTela

        //Se o título tiver vazio, busca do cadastro do cabeçalho da tabela
        If Empty(cTitulo)
            aInfoCab := FWGetSX5("00", cTabGen)
            cTitulo  := Alltrim(Capital(aInfoCab[1][4]))
        EndIf

        //Definicao do menu
        aRotina := MenuDef()

        //Adiciona as colunas que vão ser apresentadas no browse
        aAdd(aColunas, { 'Código',    'X5_CHAVE',     'C',  TamSX3('X5_CHAVE')[1],  0, ''})
        aAdd(aColunas, { 'Descrição', 'X5_DESCRI',    'C',  TamSX3('X5_DESCRI')[1], 0, ''})

        //Instanciando o browse
        oBrowse := FWMBrowse():New()
        oBrowse:SetAlias(cAliasMVC)
        oBrowse:SetOnlyFields({"X5_FILIAL"})
        oBrowse:SetFields(aColunas)
        oBrowse:SetDescription(cTitulo)
        oBrowse:DisableDetails()

        //Filtrando conforme a tabela que veio
        oBrowse:SetFilterDefault("SX5->X5_TABELA == '" + cTabGen + "'")

        //Ativa a Browse
        oBrowse:Activate()
    EndIf

	FWRestArea(aArea)
Return Nil

/*/{Protheus.doc} MenuDef
Menu de opcoes na funcao zCadSX5
@author Atilio
@since 15/02/2024
@version 1.0
@type function
/*/

Static Function MenuDef()
	Local aRotina := {}

	//Adicionando opcoes do menu
	ADD OPTION aRotina TITLE "Visualizar" ACTION "VIEWDEF.zCadSX5" OPERATION 1 ACCESS 0
	ADD OPTION aRotina TITLE "Incluir" ACTION "VIEWDEF.zCadSX5" OPERATION 3 ACCESS 0
	ADD OPTION aRotina TITLE "Alterar" ACTION "VIEWDEF.zCadSX5" OPERATION 4 ACCESS 0
	//ADD OPTION aRotina TITLE "Excluir" ACTION "VIEWDEF.zCadSX5" OPERATION 5 ACCESS 0
	ADD OPTION aRotina TITLE "Copiar" ACTION "VIEWDEF.zCadSX5" OPERATION 9 ACCESS 0

Return aRotina

/*/{Protheus.doc} ModelDef
Modelo de dados na funcao zCadSX5
@author Atilio
@since 15/02/2024
@version 1.0
@type function
/*/

Static Function ModelDef()
	Local oStruct := FWFormStruct(1, cAliasMVC)
	Local oModel
	Local bPre := Nil
	Local bPos := {|| u_zSX5Vld()}
	Local bCancel := Nil

    //Editando características do dicionário
    oStruct:SetProperty('X5_TABELA',   MODEL_FIELD_WHEN,    FwBuildFeature(STRUCT_FEATURE_WHEN,    '.F.'))                       //Modo de Edição
    oStruct:SetProperty('X5_TABELA',   MODEL_FIELD_INIT,    FwBuildFeature(STRUCT_FEATURE_INIPAD,  'cTabGen'))                   //Ini Padrão
    oStruct:SetProperty('X5_CHAVE',    MODEL_FIELD_WHEN,    FwBuildFeature(STRUCT_FEATURE_WHEN,    'Iif(INCLUI, .T., .F.)'))     //Modo de Edição
    oStruct:SetProperty('X5_CHAVE',    MODEL_FIELD_VALID,   FwBuildFeature(STRUCT_FEATURE_VALID,   'u_zSX5Vld()'))               //Validação de Campo
    oStruct:SetProperty('X5_CHAVE',    MODEL_FIELD_OBRIGAT, .T. )                                                                //Campo Obrigatório
    oStruct:SetProperty('X5_DESCRI',   MODEL_FIELD_OBRIGAT, .T. )                                                                //Campo Obrigatório

	//Cria o modelo de dados para cadastro
	oModel := MPFormModel():New("zCadSX5M", bPre, bPos, /*bCommit*/, bCancel)
	oModel:AddFields("SX5MASTER", /*cOwner*/, oStruct)
    oModel:SetPrimaryKey({'X5_FILIAL', 'X5_TABELA', 'X5_CHAVE'})
	oModel:SetDescription("Modelo de dados - " + cTitulo)
	oModel:GetModel("SX5MASTER"):SetDescription( "Dados de - " + cTitulo)
	oModel:SetPrimaryKey({})
Return oModel

/*/{Protheus.doc} ViewDef
Visualizacao de dados na funcao zCadSX5
@author Atilio
@since 15/02/2024
@version 1.0
@type function
/*/

Static Function ViewDef()
    Local cCamposPrin := "X5_CHAVE|X5_DESCRI|"
	Local oModel := FWLoadModel("zCadSX5")
	Local oStructPrin := FWFormStruct(2, cAliasMVC, {|cCampo| AllTrim(cCampo) $ cCamposPrin})
    Local oStructOutr := FWFormStruct(2, cAliasMVC, {|cCampo| ! AllTrim(cCampo) $ cCamposPrin})
	Local oView

	//Retira as abas padrões
    oStructPrin:SetNoFolder()
    oStructOutr:SetNoFolder()

    //Altera o título dos campos principais
    oStructPrin:SetProperty('X5_CHAVE',   MVC_VIEW_TITULO, 'Código')
    oStructPrin:SetProperty('X5_DESCRI',  MVC_VIEW_TITULO, 'Descrição')

    //Altera o título dos outros campos
    oStructOutr:SetProperty('X5_TABELA',  MVC_VIEW_TITULO, 'Código Interno Tabela')
    oStructOutr:SetProperty('X5_DESCSPA', MVC_VIEW_TITULO, 'Descrição Espanhol')
    oStructOutr:SetProperty('X5_DESCENG', MVC_VIEW_TITULO, 'Descrição Inglês')
 
    //Cria a visualizacao do cadastro
    oView := FWFormView():New()
    oView:SetModel(oModel)
    oView:AddField("VIEW_PRIN", oStructPrin, "SX5MASTER")
    oView:AddField("VIEW_OUTR", oStructOutr, "SX5MASTER")
 
    //Cria o controle de Abas
    oView:CreateFolder('ABAS')
    oView:AddSheet('ABAS', 'ABA_PRIN', 'Cadastro')
    oView:AddSheet('ABAS', 'ABA_OUTR', 'Outros Campos')
 
    //Cria os Box que serão vinculados as abas
    oView:CreateHorizontalBox('BOX_PRIN' ,100, /*owner*/, /*lUsePixel*/, 'ABAS', 'ABA_PRIN')
    oView:CreateHorizontalBox('BOX_OUTR' ,100, /*owner*/, /*lUsePixel*/, 'ABAS', 'ABA_OUTR')
 
    //Amarra as Abas aos Views de Struct criados
    oView:SetOwnerView('VIEW_PRIN', 'BOX_PRIN')
    oView:SetOwnerView('VIEW_OUTR', 'BOX_OUTR')

Return oView

/*/{Protheus.doc} zSX5Vld
Função que valida a digitação do campo Chave, para verificar se já existe
@type function
@author Atilio
@since 15/02/2024
@version 1.0
/*/
 
User Function zSX5Vld()
    Local aArea    := GetArea()
    Local lRet     := .T.
    Local cX5Chave := FWFldGet("X5_CHAVE")
    Local oModel   := FWModelActive()
    Local nOper    := oModel:GetOperation()

    //Se for operação de inclusão (ou a cópia)
    If nOper == 3
     
        DbSelectArea('SX5')
        SX5->(DbSetOrder(1)) // X5_FILIAL+X5_TABELA+X5_CHAVE
        SX5->(DbGoTop())
        
        //Se conseguir posicionar, já existe
        If SX5->(DbSeek(FWxFilial('SX5') + cTabGen + cX5Chave))
            ExibeHelp("Help", "Código já existe!", "Informe um código diferente.")
            lRet := .F.
        EndIf
    EndIf
     
    RestArea(aArea)
Return lRet

Fonte Original (2016)


Abaixo o exemplo do código fonte desenvolvido lá em 2016, que na época funcionava bem no Protheus 11.

//Bibliotecas
#Include 'Protheus.ch'
#Include 'FWMVCDef.ch'
 
//Variáveis Estáticas
Static cTitulo := ""
 
/*/{Protheus.doc} zCadSX5
Cadastro de tabelas SX5
@author Atilio
@since 05/08/2016
@version 1.0
    @param cTabela, character, Código da tabela genérica
    @param cTitRot, character, Título da Rotina
    @example
    u_zCadSX5("01", "Séries de NF")
/*/
 
User Function zCadSX5(cTabela, cTitRot)
    Local aArea   := GetArea()
    Local oBrowse
    Local cFunBkp := FunName()
    Default cTitRot := ""
    Private cTabX := cTabela
     
    //Senão tiver chave, finaliza    
    If Empty(cTabela)
        Return
    EndIf
     
    DbSelectArea('SX5')
    SX5->(DbSetOrder(1)) // X5_FILIAL+X5_TABELA+X5_CHAVE
    SX5->(DbGoTop())
     
    //Se vier título por parâmetro
    If !Empty(cTitRot)
        cTitulo := cTitRot
    EndIf
     
    //Se ainda tiver em branco, pega o da própria tabela
    If Empty(cTitulo)
        //Se conseguir posicionar
        If SX5->(DbSeek(FWxFilial("SX5") + "00" + cTabela))
            cTitulo := SX5->X5_DESCRI
             
        Else
            MsgAlert("Tabela não encontrada!", "Atenção")
            Return
        EndIf
    EndIf
     
    //Instânciando FWMBrowse - Somente com dicionário de dados
    SetFunName("zCadSX5")
    oBrowse := FWMBrowse():New()
     
    //Setando a tabela de cadastro de Autor/Interprete
    oBrowse:SetAlias("SX5")
 
    //Setando a descrição da rotina
    oBrowse:SetDescription(cTitulo)
     
    //Filtrando
    oBrowse:SetFilterDefault("SX5->X5_TABELA = '"+cTabela+"'")
     
    //Ativa a Browse
    oBrowse:Activate()
     
    SetFunName(cFunBkp)
    RestArea(aArea)
Return
 
/*---------------------------------------------------------------------*
 | Func:  MenuDef                                                      |
 | Autor: Daniel Atilio                                                |
 | Data:  05/08/2016                                                   |
 | Desc:  Criação do menu MVC                                          |
 *---------------------------------------------------------------------*/
 
Static Function MenuDef()
    Local aRot := {}
     
    //Adicionando opções
    ADD OPTION aRot TITLE 'Visualizar' ACTION 'VIEWDEF.zCadSX5' OPERATION MODEL_OPERATION_VIEW   ACCESS 0 //OPERATION 1
    ADD OPTION aRot TITLE 'Incluir'    ACTION 'VIEWDEF.zCadSX5' OPERATION MODEL_OPERATION_INSERT ACCESS 0 //OPERATION 3
    ADD OPTION aRot TITLE 'Alterar'    ACTION 'VIEWDEF.zCadSX5' OPERATION MODEL_OPERATION_UPDATE ACCESS 0 //OPERATION 4
    ADD OPTION aRot TITLE 'Excluir'    ACTION 'VIEWDEF.zCadSX5' OPERATION MODEL_OPERATION_DELETE ACCESS 0 //OPERATION 5
 
Return aRot
 
/*---------------------------------------------------------------------*
 | Func:  ModelDef                                                     |
 | Autor: Daniel Atilio                                                |
 | Data:  05/08/2016                                                   |
 | Desc:  Criação do modelo de dados MVC                               |
 *---------------------------------------------------------------------*/
 
Static Function ModelDef()
    //Criação do objeto do modelo de dados
    Local oModel := Nil
     
    //Criação da estrutura de dados utilizada na interface
    Local oStSX5 := FWFormStruct(1, "SX5")
     
    //Editando características do dicionário
    oStSX5:SetProperty('X5_TABELA',   MODEL_FIELD_WHEN,    FwBuildFeature(STRUCT_FEATURE_WHEN,    '.F.'))                       //Modo de Edição
    oStSX5:SetProperty('X5_TABELA',   MODEL_FIELD_INIT,    FwBuildFeature(STRUCT_FEATURE_INIPAD,  'cTabX'))                     //Ini Padrão
    oStSX5:SetProperty('X5_CHAVE',    MODEL_FIELD_WHEN,    FwBuildFeature(STRUCT_FEATURE_WHEN,    'Iif(INCLUI, .T., .F.)'))     //Modo de Edição
    oStSX5:SetProperty('X5_CHAVE',    MODEL_FIELD_VALID,   FwBuildFeature(STRUCT_FEATURE_VALID,   'u_zSX5Chv()'))               //Validação de Campo
    oStSX5:SetProperty('X5_CHAVE',    MODEL_FIELD_OBRIGAT, .T. )                                                                //Campo Obrigatório
    oStSX5:SetProperty('X5_DESCRI',   MODEL_FIELD_OBRIGAT, .T. )                                                                //Campo Obrigatório
         
    //Instanciando o modelo, não é recomendado colocar nome da user function (por causa do u_), respeitando 10 caracteres
    oModel := MPFormModel():New("zCadSX5M",/*bPre*/,/*bPos*/,/*bCommit*/,/*bCancel*/) 
     
    //Atribuindo formulários para o modelo
    oModel:AddFields("FORMSX5",/*cOwner*/,oStSX5)
     
    //Setando a chave primária da rotina
    oModel:SetPrimaryKey({'X5_FILIAL', 'X5_TABELA', 'X5_CHAVE'})
     
    //Adicionando descrição ao modelo
    oModel:SetDescription("Modelo de Dados do Cadastro "+cTitulo)
     
    //Setando a descrição do formulário
    oModel:GetModel("FORMSX5"):SetDescription("Formulário do Cadastro "+cTitulo)
Return oModel
 
/*---------------------------------------------------------------------*
 | Func:  ViewDef                                                      |
 | Autor: Daniel Atilio                                                |
 | Data:  05/08/2016                                                   |
 | Desc:  Criação da visão MVC                                         |
 *---------------------------------------------------------------------*/
 
Static Function ViewDef()
    //Criação do objeto do modelo de dados da Interface do Cadastro de Autor/Interprete
    Local oModel := FWLoadModel("zCadSX5")
     
    //Criação da estrutura de dados utilizada na interface do cadastro de Autor
    Local oStSX5 := FWFormStruct(2, "SX5")  //pode se usar um terceiro parâmetro para filtrar os campos exibidos { |cCampo| cCampo $ 'SX5_NOME|SX5_DTAFAL|'}
     
    //Criando oView como nulo
    Local oView := Nil
 
    //Criando a view que será o retorno da função e setando o modelo da rotina
    oView := FWFormView():New()
    oView:SetModel(oModel)
     
    //Atribuindo formulários para interface
    oView:AddField("VIEW_SX5", oStSX5, "FORMSX5")
     
    //Criando um container com nome tela com 100%
    oView:CreateHorizontalBox("TELA",100)
     
    //Colocando título do formulário
    oView:EnableTitleView('VIEW_SX5', 'Dados - '+cTitulo )  
     
    //Força o fechamento da janela na confirmação
    oView:SetCloseOnOk({||.T.})
     
    //O formulário da interface será colocado dentro do container
    oView:SetOwnerView("VIEW_SX5","TELA")
     
    //Retira o campo de tabela da visualização
    oStSX5:RemoveField("X5_TABELA")
Return oView
 
/*/{Protheus.doc} zSX5Chv
Função que valida a digitação do campo Chave, para verificar se já existe
@type function
@author Atilio
@since 05/08/2016
@version 1.0
/*/
 
User Function zSX5Chv()
    Local aArea    := GetArea()
    Local lRet     := .T.
    Local cX5Chave := M->X5_CHAVE
     
    DbSelectArea('SX5')
    SX5->(DbSetOrder(1)) // X5_FILIAL+X5_TABELA+X5_CHAVE
    SX5->(DbGoTop())
     
    //Se conseguir posicionar, já existe
    If SX5->(DbSeek(FWxFilial('SX5') + cTabX + cX5Chave))
        MsgAlert("Já existe chave com esse código (<b>"+cX5Chave+"</b>)!", "Atenção")
        lRet := .F.
    EndIf
     
    RestArea(aArea)
Return lRet

Bom pessoal, por hoje é só.

Abraços e até a próxima.

Dan (Daniel Atilio)
Cristão de ramificação protestante. Especialista em Engenharia de Software pela FIB, graduado em Banco de Dados pela FATEC Bauru e técnico em informática pelo CTI da Unesp. Entusiasta de soluções Open Source e blogueiro nas horas vagas. Autor e mantenedor do portal Terminal de Informação.

2 Responses

  1. Maycon disse:

    Onde devo chamar as funções estáticas?

    • Bom dia Maycon, tudo bem?

      Não entendi a dúvida. Você quer acionar as funções estáticas isoladamente?

      Pois como é um fonte em MVC, você não precisa fazer isso, basta criar uma função, por exemplo:

      User Function zTst()
          u_zCadSX5("01", "Séries NF")
      Return
      

      Ai no menu do sistema, você coloca essa função zTst.

Deixe uma resposta

Terminal de Informação