Exemplos de rotinas MVC em AdvPL

Olá pessoal…

Hoje irei mostrar 3 exemplos de rotinas MVC em AdvPL, uma Modelo 1, uma Modelo 3 e uma Modelo X.


Exemplo de Modelo 1 (apenas SBM – Grupo de Produtos), incluindo função de legenda:

Exemplo de MVC - Modelo 1

Exemplo de MVC – Modelo 1

Fonte:

//Bibliotecas
#Include 'Protheus.ch'
#Include 'FWMVCDef.ch'

//Variáveis Estáticas
Static cTitulo := "Grp.Produtos (Mod.1)"

/*/{Protheus.doc} zMVCMd1
Função para cadastro de Grupo de Produtos (SBM), exemplo de Modelo 1 em MVC
@author Atilio
@since 17/08/2015
@version 1.0
	@return Nil, Função não tem retorno
	@example
	u_zMVCMd1()
	@obs Não se pode executar função MVC dentro do fórmulas
/*/

User Function zMVCMd1()
	Local aArea   := GetArea()
	Local oBrowse
	
	//Instânciando FWMBrowse - Somente com dicionário de dados
	oBrowse := FWMBrowse():New()
	
	//Setando a tabela de cadastro de Autor/Interprete
	oBrowse:SetAlias("SBM")

	//Setando a descrição da rotina
	oBrowse:SetDescription(cTitulo)
	
	//Legendas
	oBrowse:AddLegend( "SBM->BM_PROORI == '1'", "GREEN",	"Original" )
	oBrowse:AddLegend( "SBM->BM_PROORI == '0'", "RED",	"Não Original" )
	
	//Ativa a Browse
	oBrowse:Activate()
	
	RestArea(aArea)
Return Nil

/*---------------------------------------------------------------------*
 | Func:  MenuDef                                                      |
 | Autor: Daniel Atilio                                                |
 | Data:  17/08/2015                                                   |
 | Desc:  Criação do menu MVC                                          |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function MenuDef()
	Local aRot := {}
	
	//Adicionando opções
	ADD OPTION aRot TITLE 'Visualizar' ACTION 'VIEWDEF.zMVCMd1' OPERATION MODEL_OPERATION_VIEW   ACCESS 0 //OPERATION 1
	ADD OPTION aRot TITLE 'Legenda'    ACTION 'u_zMVC01Leg'     OPERATION 6                      ACCESS 0 //OPERATION X
	//ADD OPTION aRot TITLE 'Incluir'    ACTION 'VIEWDEF.zMVCMd1' OPERATION MODEL_OPERATION_INSERT ACCESS 0 //OPERATION 3
	//ADD OPTION aRot TITLE 'Alterar'    ACTION 'VIEWDEF.zMVCMd1' OPERATION MODEL_OPERATION_UPDATE ACCESS 0 //OPERATION 4
	//ADD OPTION aRot TITLE 'Excluir'    ACTION 'VIEWDEF.zMVCMd1' OPERATION MODEL_OPERATION_DELETE ACCESS 0 //OPERATION 5

Return aRot

/*---------------------------------------------------------------------*
 | Func:  ModelDef                                                     |
 | Autor: Daniel Atilio                                                |
 | Data:  17/08/2015                                                   |
 | Desc:  Criação do modelo de dados MVC                               |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function ModelDef()
	//Criação do objeto do modelo de dados
	Local oModel := Nil
	
	//Criação da estrutura de dados utilizada na interface
	Local oStSBM := FWFormStruct(1, "SBM")
	
	//Instanciando o modelo, não é recomendado colocar nome da user function (por causa do u_), respeitando 10 caracteres
	oModel := MPFormModel():New("zMVCMd1M",/*bPre*/, /*bPos*/,/*bCommit*/,/*bCancel*/) 
	
	//Atribuindo formulários para o modelo
	oModel:AddFields("FORMSBM",/*cOwner*/,oStSBM)
	
	//Setando a chave primária da rotina
	oModel:SetPrimaryKey({'BM_FILIAL','BM_GRUPO'})
	
	//Adicionando descrição ao modelo
	oModel:SetDescription("Modelo de Dados do Cadastro "+cTitulo)
	
	//Setando a descrição do formulário
	oModel:GetModel("FORMSBM"):SetDescription("Formulário do Cadastro "+cTitulo)
Return oModel

/*---------------------------------------------------------------------*
 | Func:  ViewDef                                                      |
 | Autor: Daniel Atilio                                                |
 | Data:  17/08/2015                                                   |
 | Desc:  Criação da visão MVC                                         |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function ViewDef()
	//Criação do objeto do modelo de dados da Interface do Cadastro de Autor/Interprete
	Local oModel := FWLoadModel("zMVCMd1")
	
	//Criação da estrutura de dados utilizada na interface do cadastro de Autor
	Local oStSBM := FWFormStruct(2, "SBM")  //pode se usar um terceiro parâmetro para filtrar os campos exibidos { |cCampo| cCampo $ 'SBM_NOME|SBM_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_SBM", oStSBM, "FORMSBM")
	
	//Criando um container com nome tela com 100%
	oView:CreateHorizontalBox("TELA",100)
	
	//Colocando título do formulário
	oView:EnableTitleView('VIEW_SBM', 'Dados do Grupo de Produtos' )  
	
	//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_SBM","TELA")
Return oView

/*/{Protheus.doc} zMVC01Leg
Função para mostrar a legenda das rotinas MVC com grupo de produtos
@author Atilio
@since 17/08/2015
@version 1.0
	@example
	u_zMVC01Leg()
/*/

User Function zMVC01Leg()
	Local aLegenda := {}
	
	//Monta as cores
	AADD(aLegenda,{"BR_VERDE",		"Original"  })
	AADD(aLegenda,{"BR_VERMELHO",	"Não Original"})
	
	BrwLegenda("Grupo de Produtos", "Procedencia", aLegenda)
Return

Exemplo de Modelo 3 (SBM – Grupo de Produtos e SB1 – Produtos):

Exemplo de MVC - Modelo 3

Exemplo de MVC – Modelo 3

Fonte:

//Bibliotecas
#Include 'Protheus.ch'
#Include 'FWMVCDef.ch'

//Variáveis Estáticas
Static cTitulo := "Grp.Produtos (Mod.3)"

/*/{Protheus.doc} zMVCMd3
Função para cadastro de Grupo de Produtos (SBM) e Produtos (SB1), exemplo de Modelo 3 em MVC
@author Atilio
@since 17/08/2015
@version 1.0
	@return Nil, Função não tem retorno
	@example
	u_zMVCMd3()
	@obs Não se pode executar função MVC dentro do fórmulas
/*/

User Function zMVCMd3()
	Local aArea   := GetArea()
	Local oBrowse
	
	//Instânciando FWMBrowse - Somente com dicionário de dados
	oBrowse := FWMBrowse():New()
	
	//Setando a tabela de cadastro de Autor/Interprete
	oBrowse:SetAlias("SBM")

	//Setando a descrição da rotina
	oBrowse:SetDescription(cTitulo)
	
	//Legendas
	oBrowse:AddLegend( "SBM->BM_PROORI == '1'", "GREEN",	"Original" )
	oBrowse:AddLegend( "SBM->BM_PROORI == '0'", "RED",	"Não Original" )
	
	//Ativa a Browse
	oBrowse:Activate()
	
	RestArea(aArea)
Return Nil

/*---------------------------------------------------------------------*
 | Func:  MenuDef                                                      |
 | Autor: Daniel Atilio                                                |
 | Data:  17/08/2015                                                   |
 | Desc:  Criação do menu MVC                                          |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function MenuDef()
	Local aRot := {}
	
	//Adicionando opções
	ADD OPTION aRot TITLE 'Visualizar' ACTION 'VIEWDEF.zMVCMd3' OPERATION MODEL_OPERATION_VIEW   ACCESS 0 //OPERATION 1
	ADD OPTION aRot TITLE 'Legenda'    ACTION 'u_zMVC01Leg'     OPERATION 6                      ACCESS 0 //OPERATION X
	//ADD OPTION aRot TITLE 'Incluir'    ACTION 'VIEWDEF.zMVCMd3' OPERATION MODEL_OPERATION_INSERT ACCESS 0 //OPERATION 3
	//ADD OPTION aRot TITLE 'Alterar'    ACTION 'VIEWDEF.zMVCMd3' OPERATION MODEL_OPERATION_UPDATE ACCESS 0 //OPERATION 4
	//ADD OPTION aRot TITLE 'Excluir'    ACTION 'VIEWDEF.zMVCMd3' OPERATION MODEL_OPERATION_DELETE ACCESS 0 //OPERATION 5

Return aRot

/*---------------------------------------------------------------------*
 | Func:  ModelDef                                                     |
 | Autor: Daniel Atilio                                                |
 | Data:  17/08/2015                                                   |
 | Desc:  Criação do modelo de dados MVC                               |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function ModelDef()
	Local oModel 		:= Nil
	Local oStPai 		:= FWFormStruct(1, 'SBM')
	Local oStFilho 	:= FWFormStruct(1, 'SB1')
	Local aSB1Rel		:= {}
	
	//Criando o modelo e os relacionamentos
	oModel := MPFormModel():New('zMVCMd3M')
	oModel:AddFields('SBMMASTER',/*cOwner*/,oStPai)
	oModel:AddGrid('SB1DETAIL','SBMMASTER',oStFilho,/*bLinePre*/, /*bLinePost*/,/*bPre - Grid Inteiro*/,/*bPos - Grid Inteiro*/,/*bLoad - Carga do modelo manualmente*/)  //cOwner é para quem pertence
	
	//Fazendo o relacionamento entre o Pai e Filho
	aAdd(aSB1Rel, {'B1_FILIAL',	'BM_FILIAL'} )
	aAdd(aSB1Rel, {'B1_GRUPO',	'BM_GRUPO'}) 
	
	oModel:SetRelation('SB1DETAIL', aSB1Rel, SB1->(IndexKey(1))) //IndexKey -> quero a ordenação e depois filtrado
	oModel:GetModel('SB1DETAIL'):SetUniqueLine({"B1_FILIAL","B1_COD"})	//Não repetir informações ou combinações {"CAMPO1","CAMPO2","CAMPOX"}
	oModel:SetPrimaryKey({})
	
	//Setando as descrições
	oModel:SetDescription("Grupo de Produtos - Mod. 3")
	oModel:GetModel('SBMMASTER'):SetDescription('Modelo Grupo')
	oModel:GetModel('SB1DETAIL'):SetDescription('Modelo Produtos')
Return oModel

/*---------------------------------------------------------------------*
 | Func:  ViewDef                                                      |
 | Autor: Daniel Atilio                                                |
 | Data:  17/08/2015                                                   |
 | Desc:  Criação da visão MVC                                         |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function ViewDef()
	Local oView		:= Nil
	Local oModel		:= FWLoadModel('zMVCMd3')
	Local oStPai		:= FWFormStruct(2, 'SBM')
	Local oStFilho	:= FWFormStruct(2, 'SB1')
	
	//Criando a View
	oView := FWFormView():New()
	oView:SetModel(oModel)
	
	//Adicionando os campos do cabeçalho e o grid dos filhos
	oView:AddField('VIEW_SBM',oStPai,'SBMMASTER')
	oView:AddGrid('VIEW_SB1',oStFilho,'SB1DETAIL')
	
	//Setando o dimensionamento de tamanho
	oView:CreateHorizontalBox('CABEC',30)
	oView:CreateHorizontalBox('GRID',70)
	
	//Amarrando a view com as box
	oView:SetOwnerView('VIEW_SBM','CABEC')
	oView:SetOwnerView('VIEW_SB1','GRID')
	
	//Habilitando título
	oView:EnableTitleView('VIEW_SBM','Grupo')
	oView:EnableTitleView('VIEW_SB1','Produtos')
Return oView

Exemplo de Modelo X (SBM – Grupo de Produtos, SB1 – Produtos e SB2 – Saldo por Produto):

Exemplo de MVC - Modelo X

Exemplo de MVC – Modelo X

Fonte:

//Bibliotecas
#Include 'Protheus.ch'
#Include 'FWMVCDef.ch'

//Variáveis Estáticas
Static cTitulo := "Grp.Produtos (Mod.X)"

/*/{Protheus.doc} zMVCMdX
Função para cadastro de Grupo de Produtos (SBM), Produtos (SB1) e Saldos dos Produtos (SB2), exemplo de Modelo X em MVC
@author Atilio
@since 17/08/2015
@version 1.0
	@return Nil, Função não tem retorno
	@example
	u_zMVCMdX()
	@obs Não se pode executar função MVC dentro do fórmulas
/*/

User Function zMVCMdX()
	Local aArea   := GetArea()
	Local oBrowse
	
	//Instânciando FWMBrowse - Somente com dicionário de dados
	oBrowse := FWMBrowse():New()
	
	//Setando a tabela de cadastro de Autor/Interprete
	oBrowse:SetAlias("SBM")

	//Setando a descrição da rotina
	oBrowse:SetDescription(cTitulo)
	
	//Legendas
	oBrowse:AddLegend( "SBM->BM_PROORI == '1'", "GREEN",	"Original" )
	oBrowse:AddLegend( "SBM->BM_PROORI == '0'", "RED",	"Não Original" )
	
	//Ativa a Browse
	oBrowse:Activate()
	
	RestArea(aArea)
Return Nil

/*---------------------------------------------------------------------*
 | Func:  MenuDef                                                      |
 | Autor: Daniel Atilio                                                |
 | Data:  17/08/2015                                                   |
 | Desc:  Criação do menu MVC                                          |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function MenuDef()
	Local aRot := {}
	
	//Adicionando opções
	ADD OPTION aRot TITLE 'Visualizar' ACTION 'VIEWDEF.zMVCMdX' OPERATION MODEL_OPERATION_VIEW   ACCESS 0 //OPERATION 1
	ADD OPTION aRot TITLE 'Legenda'    ACTION 'u_zMVC01Leg'     OPERATION 6                      ACCESS 0 //OPERATION X
	//ADD OPTION aRot TITLE 'Incluir'    ACTION 'VIEWDEF.zMVCMdX' OPERATION MODEL_OPERATION_INSERT ACCESS 0 //OPERATION 3
	//ADD OPTION aRot TITLE 'Alterar'    ACTION 'VIEWDEF.zMVCMdX' OPERATION MODEL_OPERATION_UPDATE ACCESS 0 //OPERATION 4
	//ADD OPTION aRot TITLE 'Excluir'    ACTION 'VIEWDEF.zMVCMdX' OPERATION MODEL_OPERATION_DELETE ACCESS 0 //OPERATION 5

Return aRot

/*---------------------------------------------------------------------*
 | Func:  ModelDef                                                     |
 | Autor: Daniel Atilio                                                |
 | Data:  17/08/2015                                                   |
 | Desc:  Criação do modelo de dados MVC                               |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function ModelDef()
	Local oModel 		:= Nil
	Local oStPai 		:= FWFormStruct(1, 'SBM')
	Local oStFilho 	:= FWFormStruct(1, 'SB1')
	Local oStNeto 	:= FWFormStruct(1, 'SB2')
	Local aSB1Rel		:= {}
	Local aSB2Rel		:= {}
	
	//Criando o modelo e os relacionamentos
	oModel := MPFormModel():New('zMVCMdXM')
	oModel:AddFields('SBMMASTER',/*cOwner*/,oStPai)
	oModel:AddGrid('SB1DETAIL','SBMMASTER',oStFilho,/*bLinePre*/, /*bLinePost*/,/*bPre - Grid Inteiro*/,/*bPos - Grid Inteiro*/,/*bLoad - Carga do modelo manualmente*/)  //cOwner é para quem pertence
	oModel:AddGrid('SB2DETAIL','SB1DETAIL',oStNeto,/*bLinePre*/, /*bLinePost*/,/*bPre - Grid Inteiro*/,/*bPos - Grid Inteiro*/,/*bLoad - Carga do modelo manualmente*/)  //cOwner é para quem pertence
	
	//Fazendo o relacionamento entre o Pai e Filho
	aAdd(aSB1Rel, {'B1_FILIAL',	'BM_FILIAL'} )
	aAdd(aSB1Rel, {'B1_GRUPO',	'BM_GRUPO'})
	
	//Fazendo o relacionamento entre o Filho e Neto
	aAdd(aSB2Rel, {'B2_FILIAL',	'B1_FILIAL'} )
	aAdd(aSB2Rel, {'B2_COD',		'B1_COD'}) 
	
	oModel:SetRelation('SB1DETAIL', aSB1Rel, SB1->(IndexKey(1))) //IndexKey -> quero a ordenação e depois filtrado
	oModel:GetModel('SB1DETAIL'):SetUniqueLine({"B1_FILIAL","B1_COD"})	//Não repetir informações ou combinações {"CAMPO1","CAMPO2","CAMPOX"}
	oModel:SetPrimaryKey({})
	
	oModel:SetRelation('SB2DETAIL', aSB2Rel, SB2->(IndexKey(1))) //IndexKey -> quero a ordenação e depois filtrado
	oModel:GetModel('SB2DETAIL'):SetUniqueLine({"B2_COD","B2_LOCAL","B2_QATU"})	//Não repetir informações ou combinações {"CAMPO1","CAMPO2","CAMPOX"}
	oModel:SetPrimaryKey({})
	
	//Setando as descrições
	oModel:SetDescription("Grupo de Produtos - Mod. X")
	oModel:GetModel('SBMMASTER'):SetDescription('Modelo Grupo')
	oModel:GetModel('SB1DETAIL'):SetDescription('Modelo Produtos')
	oModel:GetModel('SB2DETAIL'):SetDescription('Modelo Saldos')
	
	//Adicionando totalizadores
	oModel:AddCalc('TOT_SALDO', 'SB1DETAIL', 'SB2DETAIL', 'B2_QATU', 'XX_TOTAL', 'SUM', , , "Saldo Total:" )
Return oModel

/*---------------------------------------------------------------------*
 | Func:  ViewDef                                                      |
 | Autor: Daniel Atilio                                                |
 | Data:  17/08/2015                                                   |
 | Desc:  Criação da visão MVC                                         |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function ViewDef()
	Local oView		:= Nil
	Local oModel		:= FWLoadModel('zMVCMdX')
	Local oStPai		:= FWFormStruct(2, 'SBM')
	Local oStFilho	:= FWFormStruct(2, 'SB1')
	Local oStNeto		:= FWFormStruct(2, 'SB2')
	Local oStTot		:= FWCalcStruct(oModel:GetModel('TOT_SALDO'))
	//Estruturas das tabelas e campos a serem considerados
	Local aStruSBM	:= SBM->(DbStruct())
	Local aStruSB1	:= SB1->(DbStruct())
	Local aStruSB2	:= SB2->(DbStruct())
	Local cConsSBM	:= "BM_GRUPO;BM_DESC;BM_PROORI"
	Local cConsSB1	:= "B1_COD;B1_DESC;B1_TIPO;B1_UM;B1_LOCPAD"
	Local cConsSB2	:= "B2_LOCAL;B2_QATU"
	Local nAtual		:= 0
	
	//Criando a View
	oView := FWFormView():New()
	oView:SetModel(oModel)
	
	//Adicionando os campos do cabeçalho e o grid dos filhos
	oView:AddField('VIEW_SBM',oStPai,'SBMMASTER')
	oView:AddGrid('VIEW_SB1',oStFilho,'SB1DETAIL')
	oView:AddGrid('VIEW_SB2',oStNeto,'SB2DETAIL')
	oView:AddField('VIEW_TOT', oStTot,'TOT_SALDO')
	
	//Setando o dimensionamento de tamanho
	oView:CreateHorizontalBox('CABEC',20)
	oView:CreateHorizontalBox('GRID',40)
	oView:CreateHorizontalBox('GRID2',27)
	oView:CreateHorizontalBox('TOTAL',13)
	
	//Amarrando a view com as box
	oView:SetOwnerView('VIEW_SBM','CABEC')
	oView:SetOwnerView('VIEW_SB1','GRID')
	oView:SetOwnerView('VIEW_SB2','GRID2')
	oView:SetOwnerView('VIEW_TOT','TOTAL')
	
	//Habilitando título
	oView:EnableTitleView('VIEW_SBM','Grupo')
	oView:EnableTitleView('VIEW_SB1','Produtos')
	oView:EnableTitleView('VIEW_SB2','Saldos')
	
	//Percorrendo a estrutura da SBM
	For nAtual := 1 To Len(aStruSBM)
		//Se o campo atual não estiver nos que forem considerados
		If ! Alltrim(aStruSBM[nAtual][01]) $ cConsSBM
			oStPai:RemoveField(aStruSBM[nAtual][01])
		EndIf
	Next
	
	//Percorrendo a estrutura da SB1
	For nAtual := 1 To Len(aStruSB1)
		//Se o campo atual não estiver nos que forem considerados
		If ! Alltrim(aStruSB1[nAtual][01]) $ cConsSB1
			oStFilho:RemoveField(aStruSB1[nAtual][01])
		EndIf
	Next
	
	//Percorrendo a estrutura da SB2
	For nAtual := 1 To Len(aStruSB2)
		//Se o campo atual não estiver nos que forem considerados
		If ! Alltrim(aStruSB2[nAtual][01]) $ cConsSB2
			oStNeto:RemoveField(aStruSB2[nAtual][01])
		EndIf
	Next
Return oView

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.

52 Responses

  1. Diego disse:

    Primeiramente, parabéns pelo site, tem um ótimo conteúdo. Agora algumas perguntas, onde eu posso encontrar material para estudar o modo MVC de programar? Existem cursos? Esta é uma nova tendência para o ERP da TOTVS? O ADVPL morreu??? Obrigado e novamente parabéns.

  2. silfar disse:

    Gostei muito do seu artigo. Tô com uma dificuldade aqui para mostrar os dados de campos que são virtuais na tabela filha. Esses campos são preenchidos por uma consulta padrão , na edição funciona bem , mas quando volto no cadastro ele não traz os dados, mesmo eu colocando a propriedade “inic. browse” no configutador.

  3. adailton disse:

    Olá!
    Estou utilizando seus fontes para tentar aprender, usei como base a tabela SN1, criei duas tabelas com informações complementares, há algum problema no relacionamento porque a rotina mostra o SN1 normalmente mas os dados das duas tabelas integradas, não. Você tem alguma dica para o relacionamento entre as tabelas ?

    • Dan_Atilio disse:

      Boa noite Adailton, tudo bem?
      Se for tabelas padrão, e você precisa descobrir o relacionamento, você pode usar a tabela SX9, e verificar as chaves de relacionamento.
      Agora quando é tabelas customizadas e índices customizados, recomendo sempre os campos chave terem o mesmo tamanho, por exemplo, o campo produto tem 15 caracteres, vou criar um campo em uma tabela, com o mesmo tamanho.
      Seria essa a dúvida? Ou seria alguma outra observação?
      Abraços.

      • adailton disse:

        Obrigado pela resposta!
        Mais ou menos por ai! As duas tabelas que se relacionam com o SN1 são complementos de ativos que foram penhorados ou garantidos. Acredito que o problema esteja ocorrendo porque a tabela SN1 está compartilhada e as duas tabelas customizadas estão exclusivas. A chave entre elas é Filial+CodigoBase+Item, tentei diferentes maneiras no SetRelation mas não consegui o relacionamento.
        Abraços.

        • Dan_Atilio disse:

          Boa noite Adailton ,tudo bem?
          Você poderia alterar o Array de relacionamento, por exemplo (vou utilizar a SB1 e SBM):

          aAdd(aSB1Rel, {'B1_FILIAL', 'BM_FILIAL'} )
          aAdd(aSB1Rel, {'B1_GRUPO',  'BM_GRUPO'}) 
          

          Você poderia alterar para:

          aAdd(aSB1Rel, {'B1_FILIAL', 'FWxFilial("SB1")'} )
          aAdd(aSB1Rel, {'B1_GRUPO',  'BM_GRUPO'}) 
          

          É que nos exemplos que criei, as tabelas estavam todas ou compartilhadas ou exclusivas.
          Teste dessa forma e verifique se deu certo.
          Um grande abraço.

        • adailton disse:

          Boa noite!
          Funcionou, obrigado.
          Sabe de algum fórum especificamente sobre MVC ?
          Se tivesse algum forum, as vezes minhas dúvidas poderiam já ter sido respondidas.
          Minha dúvida atual é como preencher um campo automaticamente no detalhe a partir de um dado da master.

        • Dan_Atilio disse:

          Boa noite Adailton, tudo bem?
          Vixe, um fórum sobre MVC desconheço, porém se quiser, no meu canal no YouTube, irei postar algumas aulas de MVC, dicas rápidas sabe… se quiser se inscrever e acompanhar, segue o link:
          https://www.youtube.com/channel/UCiSSA_yn20tEQdEbfo-yBKw
          Quanto ao preencher o dado, irei pesquisar e tentar desenvolver algo.
          Um grande abraço.

  4. Wanderson disse:

    Bom dia,

    Dentro do grid existe a possibilidade de inserirmos legenda?

    • Dan_Atilio disse:

      Boa noite Wanderson.
      Tentei verificar as documentações da FWFormView e da MPFormModel, não consegui encontrar nada sobre legenda ou cores nas linhas das grids.
      Se eu encontrar algo entro em contato.
      Um grande abraço.

  5. Felipo Melo disse:

    Complementando a pergunta do nosso amigo Silfar estou com o mesmo problema:

    Tenho 4 tabelas customizadas no meu modelo za1 seria field, e nas 3 grids, no segundo grid eu tenho um campo virtual, que é montado atraves do primeiro campo do segundo grid, a consulta padrao deste campo funciona, traz direitinho, porem quando seleciono, o campo virtual que esta no meu grid nao atualiza com a informação virtual, apesar do campo que o monta estar preenchido.

    Como devo fazer??

    • Dan_Atilio disse:

      Boa noite Felipo, tudo bem?
      Se eu entendi, você tem um campo F3, e um campo Virtual, é isso? E seu campo virtual não é preenchido, seria isso?
      Se sim, tente alterar o atributo de Inicializador Padrão do campo virtual, e também verifique se no dicionário de dados, existem gatilhos criados para a sua tabela, pode ser que falte algum gatilho, ou que algum interfira em outro.
      Um grande abraço.

  6. Alexandre de Andrade Gonçalves disse:

    Boa tarde meu amigo, estou usando o MVC e usei o oModel:AddCalc para jogar um campo totalizador na tela, mas nos exemplos que procurei tem apenas 1 campo totalizado, tentei adicionar 2 campos mas não consegui, tem algum modelo que tenha 2 ou mais campos totalizadores na tela?

    • Dan_Atilio disse:

      Boa tarde Alexandre, tudo bem?
      Basta, adicionar um embaixo, mudando apenas o nome do get, o campo que quer totalizar, e o tipo de totalização, ficando assim (usei como base o meu exemplo da Modelo X):

      	//Adicionando totalizadores
      	oModel:AddCalc('TOT_SALDO', 'SB1DETAIL', 'SB2DETAIL', 'B2_QATU', 'XX_TOTAL',  'SUM',   , , "Saldo Total:" )
      	oModel:AddCalc('TOT_SALDO', 'SB1DETAIL', 'SB2DETAIL', 'B2_QATU', 'XX_TOTAL2', 'COUNT', , , "Cont. Total:" )
      

      Com isso, já será gerado dois campos, como na ViewDef, adicionamos um box para o TOT_SALDO, ele já entenderá que é para buscar os dois gets.
      Espero ter ajudado.
      Qualquer dúvida, fico à disposição.
      Abraços.

  7. ANTONIO C. PATINI disse:

    Grande Daniel San, acompanho o seu blog e suas dicas sempre que recebo o newsletter, e agradeço pelas dicas que me dá quando necessito.
    Um abraço ..

  8. Neudo Campos disse:

    Boa tarde Daniel, Queria saber como faço para executar um bloco de código assim que desse um Clique duplo na Grid. Abraços

  9. Andrea disse:

    Ola Daniel estou precisando de um exemplo MVC modelo 2.

    Voce tem um para me passar

  10. Pedroza disse:

    Estou precisando utilizar parâmetros, mas da forma que era antes não estou conseguindo (validperg() e pergunte()). Tem alguma dica de como utilizar filtro?

    oModel:GetModel( ‘SRDDETAIL’ ):SetLoadFilter( { { ‘RD_DATARQ’, “MV_PAR01”, MVC_LOADFILTER_GREATER_EQUAL }, { ‘RD_DATARQ’, “MV_PAR02”, MVC_LOADFILTER_LESS_EQUAL } } )

    • Dan_Atilio disse:

      Boa tarde Pedroza, tudo bem?
      Tentou passar o conteúdo do parâmetro, ao invés do nome dele?
      Por exemplo.

      Pergunte("SuaPergunta", .F.)
      oModel:GetModel( 'SRDDETAIL' ):SetLoadFilter( { { 'RD_DATARQ', MV_PAR01, MVC_LOADFILTER_GREATER_EQUAL }, { 'RD_DATARQ', MV_PAR02, MVC_LOADFILTER_LESS_EQUAL } } )
      

      Qualquer dúvida, fico à disposição.
      Abraços.

  11. felipe disse:

    Todo material que vejo sobre mvc no advpl é sempre ligado a cadastros, o intuito é so para rotinas de cadastros mesmo? Nao vi grande vantagem… já utilizou em algum outro contexto?

    • Dan_Atilio disse:

      Boa noite Felipe.
      Então, não sei se na matriz podem ter outros focos, mas eu como programador em franquia e em clientes, 90% dos casos que utilizei MVC foi em cadastros, os outros 10% foi em Jobs com SchedDef.
      Abraços.

  12. Ivan disse:

    Olá gostaria de saber se tem como criar um formulário com duas folders e em cada uma delas utilizar a classe: FWMarkBrowse?

  13. Regis disse:

    Dan_Atilio,

    Você como faço para ocultar os campos virtuais do dicionário no cabeçalho e nos Grids? Por exemplo, no seu código abaixo você diz que se não estiver dentro da variável, o programa remove, de fato remove, mas não os virtuais.

    Ex: //Percorrendo a estrutura da SB2
    For nAtual := 1 To Len(aStruSB2)
    //Se o campo atual não estiver nos que forem considerados
    If ! Alltrim(aStruSB2[nAtual][01]) $ cConsSB2
    oStNeto:RemoveField(aStruSB2[nAtual][01])
    EndIf
    Next

  14. Matheus Matias disse:

    Boa tarde Dan_Atilio,

    voce teria como disponibilizar o completo do modelo Exemplo de MVC – Modelo X, com as opções de inclusão e alteração??

    abc

  15. Breno Nogueira disse:

    boa tarde, voce teria algum exemplo com modelo 2 em mvc, preciso criar uma rotina para a src..

  16. Antonio Alves da Silva disse:

    Boa tarde professor, gostaria de saber se é possível pegar o valor do campo XX_TOTAL e salvar no banco de dados, como se fosse um campo real, ou fazer tipo um gatilho para alimentar um campo que já esta cadastro no banco

    • Dan_Atilio disse:

      Bom dia Antonio, tudo bem?
      Eu nunca fiz, irei tentar fazer aqui em minha base de teste.
      O que você pode tentar fazer, é tentar dar um GetModel no cálculo para ver se retorna algo (tendo um tempo irei pesquisar e ver se consigo achar algo nesse sentido).

  17. Edmilson Dias Santos disse:

    Bom dia,

    Como faço para no totalizar retornar o valor final, fazendo (Credito soma), (Débito diminui) na colua XX_TOTAL, pois estou usando a seguinte:

    //Adicionando totalizadores
    oModel:AddCalc(‘TOT_SALDO’, ‘SRATITLE’, ‘SZOMASTER’, ‘ZO_QTDE’, ‘XX_TOTAL’, ‘SUM’, , , “Saldo Total:” )

  18. Ricardo Anderson disse:

    Como faço para colocar uma condições nos dados da minha view principal ?

  19. Rosange disse:

    Dan boa noite, tudo bem ? Parabéns pelo conteúdo do site.
    Pode me ajudar ? Ao inserir um produto na linha 3, preciso verificar se na linha 1 ou na linha 2 esse produto já existe. Se existir preciso replicar o preço unitário já informado anteriormente para a linha 3. Por exemplo na linha 3, digito o produto e imediatamente pesquisa nas linhas se esse produto já existe. Se existir replico o preço unitário da linha encontrada para a linha 3. Como fazer isso ?

    • Bom dia Rosange, obrigado pelo feedback.
      A lógica para percorrer a grid seria mais ou menos assim:
      1. No seu AddGrid no ModelDef, adicione um bloco de código ao validar a linha (bLinePost, por exemplo, {|| u_zSuaFuncao()}
      2. Nessa sua função customizada, você vai pegar o modelo de dados ativo (oModel := FWModelActivate())
      3. Então irá pegar a grid desse model (oModelDet := oModel:GetModel(“XXXDETAIL”))
      4. Irá fazer um laço de repetição, percorrendo do 1 ao tamanho da sua grid (oModelDet:Length())
      5. Dentro do laço, você posiciona na linha atual, por exemplo, posiciono na linha 2, 3, 4, etc (oModelDet:GoLine(nSuaLinhaDoForOuWhile))
      6. Então, você pode buscar o valor, com GetValue (oModelDet:LoadValue(“CAMPO_PRECO_UNITARIO”))

      Ai basta você adaptar com suas necessidades para replicar para outra linha com a lógica ai da empresa.
      Espero ter ajudado.
      Abraços.

  20. Cesar disse:

    Só passei por aqui para agradecer este site me ajuda muito…

  21. Antonio Carlos Pires de Oliveira disse:

    Atilio você tem um exemplo de PE em MVC que inclua um campo em uma linha de Browse sendo que esse browse foi montado com alguns campos fixados ?

Deixe uma resposta para felipeCancelar resposta

Terminal de Informação