Olá pessoal…
Hoje vou mostrar como fazer uma Modelo X em MVC (cadsatro com 3 tabelas – Pai, Filho e Neto).
Abaixo o código fonte completo usado na aula:
//Bibliotecas
#Include 'Protheus.ch'
#Include 'FWMVCDef.ch'
//Variáveis Estáticas
Static cTitulo := "Artistas (Mod.X)"
/*/{Protheus.doc} zModelX
Função de exemplo de Modelo X (Pai, Filho e Neto), com as tabelas de Artistas, CDs e Músicas
@author Atilio
@since 03/09/2016
@version 1.0
@return Nil, Função não tem retorno
@example
u_zModelX()
/*/
User Function zModelX()
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("ZZ1")
//Setando a descrição da rotina
oBrowse:SetDescription(cTitulo)
//Ativa a Browse
oBrowse:Activate()
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.zModelX' OPERATION MODEL_OPERATION_VIEW ACCESS 0 //OPERATION 1
Return aRot
/*---------------------------------------------------------------------*
| Func: ModelDef |
| Autor: Daniel Atilio |
| Data: 03/09/2016 |
| Desc: Criação do modelo de dados MVC |
*---------------------------------------------------------------------*/
Static Function ModelDef()
Local oModel := Nil
Local oStPai := FWFormStruct(1, 'ZZ1')
Local oStFilho := FWFormStruct(1, 'ZZ2')
Local oStNeto := FWFormStruct(1, 'ZZ3')
Local aZZ2Rel := {}
Local aZZ3Rel := {}
//Criando o modelo e os relacionamentos
oModel := MPFormModel():New('zModelXM')
oModel:AddFields('ZZ1MASTER',/*cOwner*/,oStPai)
oModel:AddGrid('ZZ2DETAIL','ZZ1MASTER',oStFilho,/*bLinePre*/, /*bLinePost*/,/*bPre - Grid Inteiro*/,/*bPos - Grid Inteiro*/,/*bLoad - Carga do modelo manualmente*/) //cOwner é para quem pertence
oModel:AddGrid('ZZ3DETAIL','ZZ2DETAIL',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(aZZ2Rel, {'ZZ2_FILIAL', 'ZZ1_FILIAL'} )
aAdd(aZZ2Rel, {'ZZ2_CODART', 'ZZ1_COD'})
//Fazendo o relacionamento entre o Filho e Neto
aAdd(aZZ3Rel, {'ZZ3_FILIAL', 'ZZ2_FILIAL'} )
aAdd(aZZ3Rel, {'ZZ3_CODART', 'ZZ2_CODART'})
aAdd(aZZ3Rel, {'ZZ3_CODCD', 'ZZ2_CODCD'})
oModel:SetRelation('ZZ2DETAIL', aZZ2Rel, ZZ2->(IndexKey(1))) //IndexKey -> quero a ordenação e depois filtrado
oModel:GetModel('ZZ2DETAIL'):SetUniqueLine({"ZZ2_CODCD"}) //Não repetir informações ou combinações {"CAMPO1","CAMPO2","CAMPOX"}
oModel:SetPrimaryKey({})
oModel:SetRelation('ZZ3DETAIL', aZZ3Rel, ZZ3->(IndexKey(1))) //IndexKey -> quero a ordenação e depois filtrado
oModel:GetModel('ZZ3DETAIL'):SetUniqueLine({"ZZ3_CODMUS"}) //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('ZZ1MASTER'):SetDescription('Modelo Artistas')
oModel:GetModel('ZZ2DETAIL'):SetDescription('Modelo CDs')
oModel:GetModel('ZZ3DETAIL'):SetDescription('Modelo Musicas')
//Adicionando totalizadores
oModel:AddCalc('TOTAIS', 'ZZ1MASTER', 'ZZ2DETAIL', 'ZZ2_PRECO', 'XX_VALOR', 'SUM', , , "Valor Total:" )
oModel:AddCalc('TOTAIS', 'ZZ2DETAIL', 'ZZ3DETAIL', 'ZZ3_CODMUS', 'XX_TOTAL', 'COUNT', , , "Total Musicas:" )
Return oModel
/*---------------------------------------------------------------------*
| Func: ViewDef |
| Autor: Daniel Atilio |
| Data: 03/09/2016 |
| Desc: Criação da visão MVC |
| Obs.: / |
*---------------------------------------------------------------------*/
Static Function ViewDef()
Local oView := Nil
Local oModel := FWLoadModel('zModelX')
Local oStPai := FWFormStruct(2, 'ZZ1')
Local oStFilho := FWFormStruct(2, 'ZZ2')
Local oStNeto := FWFormStruct(2, 'ZZ3')
Local oStTot := FWCalcStruct(oModel:GetModel('TOTAIS'))
//Criando a View
oView := FWFormView():New()
oView:SetModel(oModel)
//Adicionando os campos do cabeçalho e o grid dos filhos
oView:AddField('VIEW_ZZ1', oStPai, 'ZZ1MASTER')
oView:AddGrid('VIEW_ZZ2', oStFilho, 'ZZ2DETAIL')
oView:AddGrid('VIEW_ZZ3', oStNeto, 'ZZ3DETAIL')
oView:AddField('VIEW_TOT', oStTot, 'TOTAIS')
//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_ZZ1', 'CABEC')
oView:SetOwnerView('VIEW_ZZ2', 'GRID')
oView:SetOwnerView('VIEW_ZZ3', 'GRID2')
oView:SetOwnerView('VIEW_TOT', 'TOTAL')
//Habilitando título
oView:EnableTitleView('VIEW_ZZ1','Artista')
oView:EnableTitleView('VIEW_ZZ2','CDs')
oView:EnableTitleView('VIEW_ZZ3','Musicas')
//Removendo campos
oStFilho:RemoveField('ZZ2_CODART')
oStNeto:RemoveField('ZZ3_CODART')
oStNeto:RemoveField('ZZ3_CODCD')
Return oView
Bom pessoal, por hoje é só.
Abraços e até a próxima.
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”?
Se alguém puder ajudar, agradeço!
Bom dia Gabriela, tudo bem?
Vamos por partes então rs… Supondo que seu cadastro de Alunos seja a tabela, SZ1. O de matérias seja SZ3. Ai você irá montar um cadastro vinculando os dois, se você fizer em 1 única tabela (chamada Modelo 2), você teria um campo que faz vínculo na SZ1 e 1 campo na SZ2. Agora se você fizer duas tabelas, uma para vincular o aluno e dados no cabeçalho, como semestre (tabela seria SZ3), você teria que ter uma tabela de itens (SZ4), isso chamamos de Modelo 3. Depois disso, as ligações é só usar o SetRelation. Se quiser, me adicione no Skype, é daniel-atilio. Um grande abraço.
Hola Daniel:
Tengo un MVC con 3 tabelas, SC5, SC6 y ZEP, las dos primeras como sabes son de pedidos de venta, la tercera necesito que esté relacionada con cada linea del detalle (esto ya lo tengo solucionado) pero no quiero que la tercera tabela sea obligatoria, o sea puede haber registros de la SC6 sin registros asociados en la ZEP. No encuentro la manera de evitar esta validación y al querer bajar a la segunda linea de la SC6 me da un mensaje de error: EmptyForm El formulario xxxx (GRD2) no está rellenado.
Se puede solucionar esto?
Atentos Saludos
Bom dia Marcelo, tudo joia?
Rapaz, que situação inusitada. No nosso curso de MVC, eu demonstro em como fazer algo parecido na Aula 09 ( https://terminaldeinformacao.com/2022/04/22/curso-mvc-em-advpl/ ).
Porém é com 3 tabelas customizadas, ai no seu caso são 2 tabelas padrões e 1 só customizada.
Você teria algumas alternativas:
+ Tentar usar o SetOptional nessa GRD2
+ Talvez ao invés de usar a SC6 direto, usar uma FWTemporaryTable
Um grande abraço