O Modulo3, é uma função pronta que tem o mesmo efeito de uma rotina onde teremos uma janela com um cabeçalho usando a função EnChoice uma grade usando a fução MsGetDados para os itens.

O retorno da função é True quando clicamos no botão Confirmar ou False, quando clicamos no botão Fechar. É possível incluir também novos botões dentro do botão Ações Relacionadas.

Um exemplo de um Modelo3 é a rotina OMSA010 – Manutenção da Tabela de Preço

exemplo_modelo3

Uma grande vantagem de se usar o Modelo3 é a sua simplicidade, sem contar que iremos programar o mínimo possível.

Sintaxe:

Modelo3(cTitulo,cAlias1,cAlias2,aMyEncho,cLinOk,cTudoOk,nOpcE,nOpcG,cFieldOk,lVirtual,nLinhas,aAltEnchoice,nFreeze, aButtons, aCordW, nSizeHeader)

Onde:

Nome

Tipo

Descrição

cTitulo

Caracter

Titulo da janela

cAlias

Caracter

Alias da Enchoice

cAlias2

Caracter

Alias da Getdados

aMyEncho

Vetor

Array com campos da enchoice

cLinhaOk

Caracter

Função para validação da linha

cTudoOk

Caracter

Função para validação na confirmação

nOpcE

Numérico

nOpc da Enchoice

3 = Incluir , 4 = Alterar, 5 = Excluir

nOpcG

Numérico

nOpc da Getdados

3 = Incluir , 4 = Alterar, 5 = Excluir

cFieldOk

Caracter

Validação para todos os campos da GetDados

lVirtual

Lógico

Permite visualizar campos virtuais na enchoice

nLinhas

Numérico

Número máximo de linhas na getdados

aAltEnchoice

Vetor

Array com campos alteráveis da Enchoice

nFreeze

Numérico

Congelamento das colunas.

aButtons

Vetor

Array com botões de usuário na enchoicebar

aCordW

Vetor

Coordenadas da janela

nSizeHeader

Numérico

Altura da enchoice

 

No exemplo abaixo, irei mostrar como montar um modelo3 onde deixarei alguns campos habilitados para que somente estes campos sejam modificados e salvos na hora que confirmar.

Na grade, irei apresentar alguns campos, assim como a enchoice, irei definir quais campos serão salvos na hora em que confirmar a tela.

Irei trabalhar com as tabelas SC5 (Cabeçalho do Pedidos de Venda)  e SC6 (Itens dos Pedidos de Venda)

modelo3

Este fonte é chamado a partir do menu mBrowser do Pedido de Venda


User Function MA410MNU
    AADD(aRotina, {"Exemplo Modelo 3", "U_AFAT009()", 0, 4})
Return

#Include 'Protheus.ch'
User Function ExemploM3()
    Local cLinok 	:= "Allwaystrue"
    Local cTudook 	:= "Allwaystrue"
    Local nOpce 	:= 4 	//define modo de alteração para a enchoice
    Local nOpcg 	:= 4 	//define modo de alteração para o grid
    Local cFieldok 	:= "Allwaystrue"
    Local lRet 		:= .T.
    Local cMensagem := ""
    Local lVirtual  := .T. 	//Mostra campos virtuais se houver
    Local nFreeze	:= 0	
    Local nAlturaEnc:= 400	//Altura da Enchoice

    Private cCadastro	:= "Pedido de Venda"	
    Private aCols 		:= {}
    Private aHeader 	:= {}
    Private aCpoEnchoice:= {}
    Private aAltEnchoice:= {"C5_CONDPAG","C5_TPFRETE","C5_MENNOTA","C5_ZZPVCL","C5_ZZBOX","C5_ZZEQUIP","C5_ZZMOD1","C5_ZZMOD2","C5_ZZCAIXA"}
    Private cTitulo
    Private cAlias1 	:= "SC5"
    Private cAlias2 	:= "SC6"
    
    // Verifica se o pedido já está liberado
    If !Empty(SC5->C5_NOTA).Or.SC5->C5_LIBEROK=='E' .And. Empty(SC5->C5_BLQ)
        MsgStop("Este pedido está encerrado!")
    Else
        RegToMemory("SC5",.F.)
        RegToMemory("SC6",.F.)
    
        DefineCabec()
        DefineaCols(nOpcg)
        
        lRet:=Modelo3(cCadastro,cAlias1,cAlias2,aCpoEnchoice,cLinok,cTudook,nOpce,nOpcg,cFieldok,lVirtual,,aAltenchoice,nFreeze,,,nAlturaEnc)
        
        //retornará como true se clicar no botao confirmar
        if lRet
            cMensagem += "Esta rotina tem a finalidade de salvar alguns campos no PEDIDO DE VENDA LIBERADO"+CRLF+CRLF
            cMensagem += "APENAS os campos abaixo SERÃO SALVOS:"+CRLF+CRLF
            
            cMensagem += "Cabeçalho: "+CRLF
            cMensagem += "Cond.Pag,Tipo Frete,Mens.p/Nota,P.V.Cliente,Box Number,Equip/Line,Module,cont.Module,No.Caixa "+CRLF+CRLF
            
            cMensagem += "Itens:"+CRLF
            cMensagem += "Item P.C.,Num.Ped.Comp,Descrição,Data Fatura"+CRLF+CRLF

            if MsgYesNo(cMensagem+"CONFIRMA ALTERAÇÃO DOS DADOS ?", cCadastro)
                Processa({||Gravar()},cCadastro,"Alterando os dados, aguarde...")
            endif
        else
            RollbackSx8()
        endif

    Endif

Return

 
Static Function DefineCabec()
    Local aSC6		:= {"C6_ITEM","C6_ITEMPC","C6_NUMPCOM","C6_PRODUTO","C6_DESCRI","C6_ENTREG","C6_ZZENTFA","C6_QTDVEN","C6_UNSVEN","C6_QTDLIB","C6_PRCVEN","C6_PRUNIT","C6_VALOR","C6_VALDESC","C6_DESCONT","C6_TES","C6_CF","C6_IDENTB6","C6_CONTRAT","C6_ITEMCON","C6_LOTECTL","C6_NUMLOTE","C6_ENTREG","C6_ITEMED","C6_BLQ"}
    Local nUsado
    aHeader		:= {}
    aCpoEnchoice:= {}

    nUsado:=0
    
    //Monta a enchoice
    DbSelectArea("SX3")
    SX3->(DbSetOrder(1))
    dbseek(cAlias1)
    while SX3->(!eof()) .AND. X3_ARQUIVO == cAlias1
        IF X3USO(X3_USADO) .AND. CNIVEL >= X3_NIVEL
            AADD(ACPOENCHOICE,X3_CAMPO)
        endif
        dbskip()
    enddo

    //Monta o aHeader do grid conforme os campos definidos no array aSC6 (apenas os campos que deseja)
    //Caso contrário, se quiser todos os campos é necessário trocar o "For" por While, para que este faça a leitura de toda a tabela
    DbSelectArea("SX3")
    SX3->(DbSetOrder(2))
    aHeader:={}
    For nX := 1 to Len(aSC6)
        If SX3->(DbSeek(aSC6[nX]))
            If X3USO(X3_USADO).And.cNivel>=X3_NIVEL 
                nUsado:=nUsado+1
                Aadd(aHeader, {TRIM(X3_TITULO), X3_CAMPO , X3_PICTURE, X3_TAMANHO, X3_DECIMAL,X3_VALID, X3_USADO  , X3_TIPO   , X3_ARQUIVO, X3_CONTEXT})
            Endif
        Endif
    Next nX

 	 
Return
 
//Insere o conteudo no aCols do grid
Static function DefineaCols(nOpc)
    Local nQtdcpo 	:= 0
    Local i			:= 0
    Local nCols 	:= 0
    nQtdcpo 		:= len(aHeader)
    aCols			:= {}
    
    dbselectarea(cAlias2)
    dbsetorder(1)
    dbseek(xfilial(cAlias2)+(cAlias1)->C5_NUM)
    while .not. eof() .and. (cAlias2)->C6_FILIAL == xfilial(cAlias2) .and. (cAlias2)->C6_NUM==(cAlias1)->C5_NUM
        aAdd(aCols,array(nQtdcpo+1))
        nCols++
        for i:= 1 to nQtdcpo
            if aHeader[i,10] <> "V"
                aCols[nCols,i] := Fieldget(Fieldpos(aHeader[i,2]))
            else
                aCols[nCols,i] := Criavar(aHeader[i,2],.T.)
            endif
        next i
        aCols[nCols,nQtdcpo+1] := .F.
        dbselectarea(cAlias2)
        dbskip()
    enddo
Return
 

//Gravar o conteudo dos campos
Static Function Gravar()
    Local bcampo := { |nfield| field(nfield) }
    Local i:= 0
    Local y:= 0
    Local nitem := 0
    Local nItem 	:= aScan(aHeader,{|x| AllTrim(Upper(x[2]))=="C6_ITEM"})
    Local nProduto 	:= aScan(aHeader,{|x| AllTrim(Upper(x[2]))=="C6_PRODUTO"})
    Local nPosCpo
    Local nCpo
    Local nI
    Local cCamposSC5	:= "C5_CONDPAG|C5_TPFRETE|C5_MENNOTA|C5_ZZPVCL|C5_ZZBOX|C5_ZZEQUIP|C5_ZZMOD1|C5_ZZMOD2|C5_ZZCAIXA" 
    Local cCamposSC6	:= "C6_ITEMPC|C6_NUMPCOM|C6_DESCRI|C6_ZZENTFA" 

    Begin Transaction
    
        //Gravando dados da enchoice
        dbselectarea(cAlias1)
        Reclock(cAlias1,.F.)	 
        for i:= 1 to fcount()
            incproc()
            if "FILIAL" $ FIELDNAME(i)
                Fieldput(i,xfilial(cAlias1))
            else
                //Grava apenas os campos contidos na variavel cCamposSC5
                If ( FieldName(i) $ cCamposSC5 )
                    Fieldput(i,M->&(EVAL(bcampo,i)))
                Endif
            endif
        next i		 
        Msunlock()
    
        //Gravando dados do grid
        dbSelectArea("SC6")
        SC6->(dbSetOrder(1))	
        For nI := 1 To Len(aCols)
            If !(aCols[nI, Len(aHeader)+1])
                If SC6->(dbSeek( xFilial("SC6")+M->C5_NUM+aCols[nI,nItem]+aCols[nI,nProduto] ))
                    RecLock("SC6",.F.)
                    For nCpo := 1 to fCount()
                        //Grava apenas os campos contidos na variavel $cCamposSC6
                        If (FieldName(nCpo)$cCamposSC6)
                            nPosCpo := aScan(aHeader,{|x| AllTrim(x[2]) == AllTrim(FieldName(nCpo))})
                            If nPosCpo > 0
                                FieldPut(nCpo,aCols[nI,nPosCpo])
                            EndIf
                        Endif
                    Next nCpo
                    SC6->(MsUnLock())
                Endif
            Endif
        Next nI
        
    End Transaction
Return

Recomendo também a função do colega Marinado de Jesus, vide URL http://totvs-advpl-naldodj.googlecode.com/svn-history/r2/trunk/templates/P10/ndj_01/Projeto/NDJLib/NDJLib005.prg , a sua função está bem mais completa que a padrão Totvs.

 

Espero que o exemplo tenha sido útil!


Equipe Blog Advpl

Amantes da tecnologia

4 comentários

User Function · 16 de junho de 2015 às 14:16

Legal o artigo… realmente se formos fazer ‘na mão’ um modelo3 nós perderíamos um tempinho mesmo…

E, melhor do que isso seria irmos para o MVC mesmo né?

Parabéns pelo post!

Leonardo
http://www.userfunction.com.br

    Equipe Blog Advpl · 19 de junho de 2015 às 08:51

    Tanto o modelo2, quanto o modelo3 é uma boa alternativa para quem ainda não conheceu o MVC do Protheus.
    Em breve postarei o modelo2 e mais exemplos de MVC

      jmfrolim · 20 de julho de 2015 às 16:46

      Eu sempre acompanho o blog, acho que seria interessante e mais didatico, separar cada trecho e descrever o que cada trecho faz, pois ai quem acompanha e vai fazer os exemplos tem uma explicação do que o trecho de codigo faz, pois quem esta começando muitas vezes não consegue acompanha por não entender algo.
      Mas o artigo esta exelente!

        Equipe Blog Advpl · 21 de julho de 2015 às 07:56

        Olá João. Agradecemos pela dica, iremos reformular nosso site deixando-o mais didático possível.
        abraços
        Equipe BlogAdvpl

Deixe uma resposta