Olá pessoal…
Hoje vou mostrar uma aula em MVC para alterar as validações padrões bPre, bPos, bCommit e bCancel.
Abaixo o código fonte completo usado na aula:
//Bibliotecas
#Include 'Protheus.ch'
#Include 'FWMVCDef.ch'
//Variáveis Estáticas
Static cTitulo := "Artista"
Static cDefault := "NOME DO ARTISTA"
/*/{Protheus.doc} zMod1b
Exemplo de Modelo 1 para cadastro de Artistas com validações
@author Atilio
@since 03/09/2016
@version 1.0
@return Nil, Função não tem retorno
@example
u_zMod1b()
/*/
User Function zMod1b()
Local aArea := GetArea()
Local oBrowse
Local cFunBkp := FunName()
SetFunName("zMod1b")
//Instânciando FWMBrowse - Somente com dicionário de dados
oBrowse := FWMBrowse():New()
//Setando a tabela de cadastro de Autor/Interprete
oBrowse:SetAlias("ZZ1")
//Setando a descrição da rotina
oBrowse:SetDescription(cTitulo)
//Ativa a Browse
oBrowse:Activate()
SetFunName(cFunBkp)
RestArea(aArea)
Return Nil
/*---------------------------------------------------------------------*
| Func: MenuDef |
| Autor: Daniel Atilio |
| Data: 03/09/2016 |
| Desc: Criação do menu MVC |
*---------------------------------------------------------------------*/
Static Function MenuDef()
Local aRot := {}
//Adicionando opções
ADD OPTION aRot TITLE 'Visualizar' ACTION 'VIEWDEF.zMod1b' OPERATION MODEL_OPERATION_VIEW ACCESS 0 //OPERATION 1s
ADD OPTION aRot TITLE 'Incluir' ACTION 'VIEWDEF.zMod1b' OPERATION MODEL_OPERATION_INSERT ACCESS 0 //OPERATION 3
ADD OPTION aRot TITLE 'Alterar' ACTION 'VIEWDEF.zMod1b' OPERATION MODEL_OPERATION_UPDATE ACCESS 0 //OPERATION 4
ADD OPTION aRot TITLE 'Excluir' ACTION 'VIEWDEF.zMod1b' OPERATION MODEL_OPERATION_DELETE ACCESS 0 //OPERATION 5
Return aRot
/*---------------------------------------------------------------------*
| Func: ModelDef |
| Autor: Daniel Atilio |
| Data: 03/09/2016 |
| Desc: Criação do modelo de dados MVC |
*---------------------------------------------------------------------*/
Static Function ModelDef()
//Blocos de código nas validações
Local bVldPre := {|| u_zM1bPre()} //Antes de abrir a Tela
Local bVldPos := {|| u_zM1bPos()} //Validação ao clicar no Confirmar
Local bVldCom := {|| u_zM1bCom()} //Função chamadao ao cancelar
Local bVldCan := {|| u_zM1bCan()} //Função chamadao ao cancelar
//Criação do objeto do modelo de dados
Local oModel := Nil
//Criação da estrutura de dados utilizada na interface
Local oStZZ1 := FWFormStruct(1, "ZZ1")
//Editando características do dicionário
oStZZ1:SetProperty('ZZ1_COD', MODEL_FIELD_WHEN, FwBuildFeature(STRUCT_FEATURE_WHEN, '.F.')) //Modo de Edição
oStZZ1:SetProperty('ZZ1_COD', MODEL_FIELD_INIT, FwBuildFeature(STRUCT_FEATURE_INIPAD, 'GetSXENum("ZZ1", "ZZ1_COD")')) //Ini Padrão
oStZZ1:SetProperty('ZZ1_DESC', MODEL_FIELD_OBRIGAT, Iif(RetCodUsr()!='000000', .T., .F.) ) //Campo Obrigatório
oStZZ1:SetProperty('ZZ1_DESC', MODEL_FIELD_INIT, FwBuildFeature(STRUCT_FEATURE_INIPAD, "'"+cDefault+"'")) //Ini Padrão
//Instanciando o modelo, não é recomendado colocar nome da user function (por causa do u_), respeitando 10 caracteres
oModel := MPFormModel():New("zMod1bM", bVldPre, bVldPos, bVldCom, bVldCan)
//Atribuindo formulários para o modelo
oModel:AddFields("FORMZZ1",/*cOwner*/,oStZZ1)
//Setando a chave primária da rotina
oModel:SetPrimaryKey({'ZZ1_FILIAL','ZZ1_COD'})
//Adicionando descrição ao modelo
oModel:SetDescription("Modelo de Dados do Cadastro "+cTitulo)
//Setando a descrição do formulário
oModel:GetModel("FORMZZ1"):SetDescription("Formulário do Cadastro "+cTitulo)
//Pode ativar?
oModel:SetVldActive( { | oModel | fAlterar( oModel ) } )
Return oModel
/*---------------------------------------------------------------------*
| Func: ViewDef |
| Autor: Daniel Atilio |
| Data: 03/09/2016 |
| Desc: Criação da visão MVC |
*---------------------------------------------------------------------*/
Static Function ViewDef()
Local aStruZZ1 := ZZ1->(DbStruct())
//Criação do objeto do modelo de dados da Interface do Cadastro de Autor/Interprete
Local oModel := FWLoadModel("zMod1b")
//Criação da estrutura de dados utilizada na interface do cadastro de Autor
Local oStZZ1 := FWFormStruct(2, "ZZ1") //pode se usar um terceiro parâmetro para filtrar os campos exibidos { |cCampo| cCampo $ 'SZZ1_NOME|SZZ1_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_ZZ1", oStZZ1, "FORMZZ1")
//Criando um container com nome tela com 100%
oView:CreateHorizontalBox("TELA",100)
//Colocando título do formulário
oView:EnableTitleView('VIEW_ZZ1', '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_ZZ1","TELA")
Return oView
/*/{Protheus.doc} zM1bPre
Função chamada na criação do Modelo de Dados (pré-validação)
@type function
@author Atilio
@since 03/09/2016
@version 1.0
/*/
User Function zM1bPre()
Local oModelPad := FWModelActive()
Local nOpc := oModelPad:GetOperation()
Local lRet := .T.
//Se for inclusão ou exclusão
If nOpc == MODEL_OPERATION_INSERT
If RetCodUsr() == '000000'
oModelPad:GetModel('FORMZZ1'):GetStruct():SetProperty('ZZ1_COD', MODEL_FIELD_WHEN, FwBuildFeature(STRUCT_FEATURE_WHEN, '.T.'))
EndIf
EndIf
Return lRet
/*/{Protheus.doc} zM1bPos
Função chamada no clique do botão Ok do Modelo de Dados (pós-validação)
@type function
@author Atilio
@since 03/09/2016
@version 1.0
/*/
User Function zM1bPos()
Local oModelPad := FWModelActive()
Local cDescri := oModelPad:GetValue('FORMZZ1', 'ZZ1_DESC')
Local lRet := .T.
//Se a descrição estiver em branco
If Empty(cDescri) .Or. Alltrim(Upper(cDescri)) == cDefault
lRet := .F.
Aviso('Atenção', 'Campo Descrição esta em branco!', {'OK'}, 03)
EndIf
Return lRet
/*/{Protheus.doc} zM1bCom
Função chamada após validar o ok da rotina para os dados serem salvos
@type function
@author Atilio
@since 03/09/2016
@version 1.0
/*/
User Function zM1bCom()
Local oModelPad := FWModelActive()
Local cCodigo := oModelPad:GetValue('FORMZZ1', 'ZZ1_COD')
Local cDescri := oModelPad:GetValue('FORMZZ1', 'ZZ1_DESC')
Local nOpc := oModelPad:GetOperation()
Local lRet := .T.
//Se for Inclusão
If nOpc == MODEL_OPERATION_INSERT
RecLock('ZZ1', .T.)
ZZ1_FILIAL := FWxFilial('ZZ1')
ZZ1_COD := cCodigo
ZZ1_DESC := cDescri
ZZ1->(MsUnlock())
ConfirmSX8()
Aviso('Atenção', 'Inclusão realizada!', {'OK'}, 03)
//Se for Alteração
ElseIf nOpc == MODEL_OPERATION_UPDATE
RecLock('ZZ1', .F.)
ZZ1_DESC := cDescri
ZZ1->(MsUnlock())
Aviso('Atenção', 'Alteração realizada!', {'OK'}, 03)
//Se for Exclusão
ElseIf nOpc == MODEL_OPERATION_DELETE
RecLock('ZZ1', .F.)
DbDelete()
ZZ1->(MsUnlock())
Aviso('Atenção', 'Exclusão realizada!', {'OK'}, 03)
EndIf
Return lRet
/*/{Protheus.doc} zM1bCan
Função chamada ao cancelar as informações do Modelo de Dados (botão Cancelar)
@type function
@author Atilio
@since 03/09/2016
@version 1.0
/*/
User Function zM1bCan()
Local oModelPad := FWModelActive()
Local lRet := .T.
//Somente permite cancelar se o usuário confirmar
lRet := MsgYesNo("Deseja cancelar a operação?", "Atenção")
Return lRet
/*---------------------------------------------------------------------*
| Func: fAlterar |
| Autor: Daniel Atilio |
| Data: 03/09/2016 |
| Desc: Define se pode abrir o Modelo de Dados |
*---------------------------------------------------------------------*/
Static Function fAlterar( oModel )
Local lRet := .T.
Local nOperation := oModel:GetOperation()
//Se for exclusão
If nOperation == MODEL_OPERATION_DELETE
//Se não for o Administrador
If RetCodUsr() != '000000'
lRet := .F.
Aviso('Atenção', 'Somente o Administrador pode excluir registros!', {'OK'}, 03)
EndIf
EndIf
Return lRet
Bom pessoal, por hoje é só.
Abraços e até a próxima.
Parabéns pelo exemplo Daniel estou utilizando sempre aqui na empresa, abraços.
Grande Robs.
Obrigado jovem.
Aquele abraço.
Parabéns pelo excelente exemplo MVC.Com certeza ajudará muitos analistas
Boa noite Artur.
Eu que agradeço jovem.
Um grande abraço.
Grato pelo excelente conteúdo em MVC! Gostaria de deixar a sugestão de um artigo informando como inserir um botão com chamada para uma outra tela utilizando o ponto de entrada BUTTON..
Boa noite Allan, tudo bem?
Na verdade já preparei o fonte para essa aula de pontos de entrada em MVC, mas está muito corrido esse fim de ano.
Pode ficar tranquilo, que será postado sim.
Um grande abraço.
Boa tarde, Prof Daniel!! Ótima aula! Porém minha situação se difere um pouco, gostaria de saber se tens alguma sugestão:
Tenho um cadastro “ALUNOS”, um segundo cadastro “MATÉRIAS” e um terceiro “ALUNOxMATÉRIAS”. Considerando relacionamento de 1 aluno para N matérias, gostaria de saber como posso fazer a relação entre essas três tabelas( “ALUNOS”,”MATÉRIAS” e “ALUNOxMATÉRIAS”).
Como faço para, no cadastro “ALUNOS”, mostrar as matérias em que este está cadastrado, por exemplo?
ou como posso, no cadastro “ALUNOxMATÉRIAS”, ligar 1 registro da tabela “ALUNOS” a um registro da tabela “MATÉRIAS”?
Obs.
A tabela “ALUNOxMATÉRIAS” possui os campos “FILIAL”, “COD_ALUNO” e “COD_MATERIA”.
A tabela “ALUNOS” possui os campos “FILIAL”, “COD_ALUNO” e “NOME”
A tabela “MATÉRIAS” possui os campos “FILIAL”, “COD_MATERIA” e “NOME_MATERIA”
Bom dia Gabriela, tudo bem?
Nesse exemplo, você poderia criar uma tabela de vínculo, que conteria o COD_ALUNO, COD_MATERIA e algum outro campo, como observação.
Ai você poderia cadastrar isso em uma Modelo 2 mesmo.
Um grande abraço.
Boa tarde professor Daniel, estou com a seguinte dúvida:
Static Function fAlterar(oModel)
Local lRet := .T.
Local nOperation := oModel:GetOperation()
//Se for exclusão
If nOperation == MODEL_OPERATION_DELETE
//Se não for o Administrador
If RetCodUsr() != ‘000000’
lRet := .F.
Aviso(‘Atenção’, ‘Somente o Administrador pode excluir registros!’, {‘OK’}, 03)
EndIf
EndIf
Return lRet
como faria para bloquear a exclusão caso minha rotina estivesse com a legenda vermelha de encerrado?
Desde já agradeço
Bom dia jovem, tudo bem?
Se eu entendi bem, você gostaria de bloquear uma operação se sua legenda estivesse vermelha.
Acho que a forma mais fácil, é pegar a condição da sua legenda (por exemplo, TAB->CAMPO == ‘1’), copiar e colocar em um If, e se cair dentro desse If, o seu lRet vai ser falso (.F.).
Qualquer dúvida, fico à disposição.
Um grande abraço.
Boa tarde professor Daniel!
na Static Function fAlterar(), como faria para bloquear a exclusão se a minta rotina estivesse com a legenda vermelha de encerrada?
Desde já agradeço.
Boa tarde Atilio,
Eu estou usando esse seu exemplo para aplicar uma “validação” no bcommit de uma alteração em um grid tipo do seu exemplo zmodel3
Se eu aplico sua validação como no exemplo apresentando uma mensagem ela funciona perfeitamente, mas nesse momento eu tambem executo um msexecauto que faz uma baixa no SD3 e usando o execauto, a gravação em si do grid para de funcionar. O execauto funciona perfeitamente mas o grid que eu estava fazendo a alteração não se altera. Imagino que seja algo como um desposicionamento e imagino que eu tenha que forçar a gravação agora por conta disso. Tem algum exemplo de como eu posso gravar os dados do grid que estou posicionado…pois a função do “Bcommit” com o execauto não faz mais a atualização dos dados do cadastro….obrigado
Bom dia Mauricio, tudo joia?
Então, esse é um exemplo bem antigo (2016), acontece que o bCommit foi descontinuado em MVC, e foi substituído pelo FWModelEvent.
Ai dentro dele você vai ter o BeforeTTS (antes da gravação), o InTTS (durante a gravação) e o AfterTTS (após a gravação).
Nesse link tem um exemplo completo de como migrar do antigo bCommit para essa forma nova: https://terminaldeinformacao.com/2023/03/24/como-utilizar-a-fwmodelevent-no-lugar-do-commit-em-uma-rotina-mvc/
Tenha um ótimo e abençoado fim de semana.
Um grande abraço.