#Include "Protheus.ch" #Include "FWMVCDef.ch" /*/{Protheus.doc} PGV010 Cadastro de tipos de contrato (tabela ficticia Z50) escrito em MVC, no formato de entidade unica -- o "modelo 1" do ERP. Este fonte e um MVC didatico completo: alem da funcao principal, tem so as tres Static Function de nome obrigatorio que o framework procura -- MenuDef, ModelDef e ViewDef. Nao ha uma linha de gravacao, porque quem grava e o FWFormCommit que o MPFormModel instala sozinho. Exemplo didatico do site. As tabelas Z50 nao existem no dicionario padrao; crie-as no Configurador antes de compilar. @type user function @author Pragiva @since 20/09/2026 @version 1.0 @return nil @example U_PGV010() /*/ User Function PGV010() Local oBrowse := Nil oBrowse := FWMBrowse():New() oBrowse:SetAlias("Z50") oBrowse:SetDescription("Tipos de contrato") // O browse precisa saber de QUE FONTE ler o MenuDef. E o nome do // arquivo, nao o da funcao. oBrowse:SetMenuDef("PGV010") oBrowse:AddLegend("Z50_STATUS == '1'", "GREEN", "Ativo") oBrowse:AddLegend("Z50_STATUS == '2'", "RED" , "Inativo") oBrowse:Activate() Return Nil /*/{Protheus.doc} MenuDef As opcoes do browse. O comando ADD OPTION e do FWMBrowse.ch, que o FWMVCDef.ch inclui: ele so faz um aAdd de um array de seis posicoes -- titulo, acao, 0, operacao, acesso, desabilita-menu. Todas as opcoes de edicao apontam para a MESMA acao, "VIEWDEF.PGV010". O que distingue incluir de alterar e o numero do OPERATION. @type static function @return array, o aRotina do browse /*/ Static Function MenuDef() Local aRotina := {} ADD OPTION aRotina TITLE "Pesquisar" ACTION "AxPesqui" OPERATION 1 ACCESS 0 ADD OPTION aRotina TITLE "Visualizar" ACTION "VIEWDEF.PGV010" OPERATION 2 ACCESS 0 ADD OPTION aRotina TITLE "Incluir" ACTION "VIEWDEF.PGV010" OPERATION 3 ACCESS 0 ADD OPTION aRotina TITLE "Alterar" ACTION "VIEWDEF.PGV010" OPERATION 4 ACCESS 0 ADD OPTION aRotina TITLE "Excluir" ACTION "VIEWDEF.PGV010" OPERATION 5 ACCESS 0 Return aRotina /*/{Protheus.doc} ModelDef O modelo de dados: o que existe, o que vale e como grava. MPFormModel herda de FWFormModel e so muda os valores padrao do construtor: quem instancia MPFormModel ja recebe FWFormCommit como bloco de gravacao, FWFormCancel como bloco de cancelamento e FWFormCanDel como pos-validacao. E por isso que este fonte grava sem ter uma linha de RecLock. @type static function @return object, o modelo pronto para a view consumir /*/ Static Function ModelDef() Local oModel := Nil // 1 monta a estrutura do MODELO, a partir do dicionario (SX3). Local oStruct := FWFormStruct(1, "Z50") oModel := MPFormModel():New("PGV010M") // O segundo parametro e o dono (cOwner). O componente principal nao tem // dono, entao vai vazio. oModel:AddFields("Z50MASTER", /*cOwner*/, oStruct) oModel:SetDescription("Tipos de contrato") oModel:GetModel("Z50MASTER"):SetDescription("Dados do tipo de contrato") oModel:SetPrimaryKey({"Z50_FILIAL", "Z50_COD"}) Return oModel /*/{Protheus.doc} ViewDef A tela. Nao decide nada: recebe o modelo pronto e diz onde cada coisa aparece. FWLoadModel("PGV010") e, por dentro, uma chamada a STATICCALL(PGV010, ModelDef) -- e dai vem a regra de que o argumento e o nome do FONTE e de que ModelDef precisa se chamar exatamente assim. @type static function @return object, a view ligada ao modelo /*/ Static Function ViewDef() Local oView := Nil Local oModel := FWLoadModel("PGV010") // 2 monta a estrutura da VIEW. E outra chamada, para o mesmo alias: // modelo e tela leem o dicionario cada um para si. Local oStruct := FWFormStruct(2, "Z50") oView := FWFormView():New() oView:SetModel(oModel) // O terceiro parametro liga o componente da tela ao componente do // modelo. Os dois IDs podem ser diferentes; e esse argumento que os une. oView:AddField("VIEW_Z50", oStruct, "Z50MASTER") oView:CreateHorizontalBox("TELA", 100) // Sem SetOwnerView o componente existe e nao aparece. oView:SetOwnerView("VIEW_Z50", "TELA") Return oView