Exemplos de rotinas MVC em AdvPL

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

Esses e outros códigos, estão disponíveis gratuitamente no nosso GitHub, acesse em github.com/dan-atilio/AdvPL.

Bom pessoal, por hoje é só.
Abraços e até a próxima.

About Dan_Atilio

Analista e desenvolvedor de sistemas. Técnico em Informática pelo CTI da Unesp. Graduado em Banco de Dados pela Fatec Bauru. Entusiasta de soluções Open Source e blogueiro nas horas vagas. Autor do projeto Terminal de Informação, onde são postados tutoriais e notícias envolvendo o mundo da tecnologia.

37 comentários em “Exemplos de rotinas MVC em AdvPL

  1. 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.

    1. Boa noite Diego.
      Muito Obrigado.
      Então, o único material que encontrei pela internet foi pelo TDN: http://tdn.totvs.com/display/public/mp/AdvPl+utilizando+MVC;jsessionid=37539EC97401D95FDC5DEB859A57DB32
      Agora, cursos, não sei se existem, acho que não, estava pensando em fazer vídeo-aulas explicando um pouco.
      E sim, é uma nova tendência, pois querem facilitar o desenvolvimento.
      Quanto ao AdvPL, ele continua vivo e forte, rs… na verdade MVC é apenas uma Tecnologia utilizada pelo AdvPL.
      Agradeço novamente e um grande abraço.

  2. 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. 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 ?

    1. 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.

      1. 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.

        1. 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.

        2. 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.

    1. 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.

  4. 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??

    1. 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.

  5. 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?

    1. 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.

  6. 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 ..

    1. Boa noite Neudo.
      Mas ao dar duplo clique na grid, vc iria para a edição de um campo, certo?
      Porque dae, você estaria substituindo a tratativa padrão do framework, em teoria é possível, mas na prática nunca precisei fazer.

  7. 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 } } )

    1. 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.

  8. 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?

    1. 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.

  9. 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

  10. 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

Deixe uma resposta

%d blogueiros gostam disto: