Como fazer um AddCalc manualmente em MVC

No artigo de hoje, vamos demonstrar em como criar um AddCalc utilizando o tipo FORMULA para podermos montar uma função que atualiza os dados.

Pessoal, quando estava montando esse artigo, me deparei com um cenário, se você for ter um AddCalc que não irá sofrer alterações, ai a rotina pode funcionar muito bem.

 

Porém se você quer por exemplo, que ao alternar de linha, seja acionado a atualização do AddCalc, ai poderá ocasionar um pequeno problema de delay de informação.

 

Por exemplo, no teste que montei, o cabeçalho é o grupo de produtos (SBM) e a grid são os produtos (SB1), ao alternar entre as linhas da grid, é exibido o saldo do produto (SB2).

 

Na nossa base de testes, temos o produto Kiwi que tem 31 com saldo em estoque, acontece que ao usar o AddCalc junto com o CHANGELINE (na SetViewProperty), ele atualiza em forma atrasada.

 

Então abaixo uma descrição do que esta acontecendo:

  • A tela abre, e ele mostra o saldo do produto posicionado
  • Cliquei no produto Kiwi, ainda mostra o do produto posicionado anteriormente
  • Cliquei em outro produto, ai sim mostra o saldo do produto Kiwi

Para esse cenário, como podemos resolver então? O que fizemos foi utilizar o AddOtherObject, e criar manualmente um TGet que é atualizado assim que clicamos na linha, totalizando corretamente. Ao clicar no produto, exibe o saldo correto do produto.

 

Abaixo segue os dois códigos com os gifs de cada um.

Usando AddOtherObject

Exemplo utilizando AddOtherObject

//Bibliotecas
#Include "Totvs.ch"
#Include "FWMVCDef.ch"
 
//Variveis Estaticas
Static cTitulo := "Grupo x Produtos"
Static cTabPai := "SBM"
Static cTabFilho := "SB1"
 
/*/{Protheus.doc} User Function zTstPr2
Grupo x Produtos
@author Atilio
@since 11/01/2023
@version 1.0
@type function
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
/*/
 
User Function zTstPr2()
    Local aArea   := FWGetArea()
    Local oBrowse
    Private aRotina := {}
    Private bBlocoAtu := {|| fAtualiza()}
    Private oGetObj, nSaldo := 0
 
    //Definicao do menu
    aRotina := MenuDef()
 
    //Instanciando o browse
    oBrowse := FWMBrowse():New()
    oBrowse:SetAlias(cTabPai)
    oBrowse:SetDescription(cTitulo)
    oBrowse:DisableDetails()
 
    //Ativa a Browse
    oBrowse:Activate()
 
    FWRestArea(aArea)
Return Nil
 
/*/{Protheus.doc} MenuDef
Menu de opcoes na funcao zTstPr2
@author Atilio
@since 11/01/2023
@version 1.0
@type function
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
/*/
 
Static Function MenuDef()
    Local aRotina := {}
 
    //Adicionando opcoes do menu
    ADD OPTION aRotina TITLE "Visualizar" ACTION "VIEWDEF.zTstPr2" OPERATION 1 ACCESS 0
 
Return aRotina
 
/*/{Protheus.doc} ModelDef
Modelo de dados na funcao zTstPr2
@author Atilio
@since 11/01/2023
@version 1.0
@type function
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
/*/
 
Static Function ModelDef()
    Local oStruPai := FWFormStruct(1, cTabPai)
    Local oStruFilho := FWFormStruct(1, cTabFilho)
    Local aRelation := {}
    Local oModel
    Local bPre := bBlocoAtu
    Local bPos := Nil
    Local bCommit := Nil
    Local bCancel := Nil
 
 
    //Cria o modelo de dados para cadastro
    oModel := MPFormModel():New("zTstPr2M", bPre, bPos, bCommit, bCancel)
    oModel:AddFields("SBMMASTER", /*cOwner*/, oStruPai)
    oModel:AddGrid("SB1DETAIL","SBMMASTER",oStruFilho,/*bLinePre*/, /*bLinePost*/,/*bPre - Grid Inteiro*/,/*bPos - Grid Inteiro*/,/*bLoad - Carga do modelo manualmente*/)
    oModel:SetDescription("Modelo de dados - " + cTitulo)
    oModel:GetModel("SBMMASTER"):SetDescription( "Dados de - " + cTitulo)
    oModel:GetModel("SB1DETAIL"):SetDescription( "Grid de - " + cTitulo)
    oModel:SetPrimaryKey({})
 
    //Fazendo o relacionamento
    aAdd(aRelation, {"B1_FILIAL", "FWxFilial('SB1')"} )
    aAdd(aRelation, {"B1_GRUPO", "BM_GRUPO"})
    oModel:SetRelation("SB1DETAIL", aRelation, SB1->(IndexKey(1)))
 
Return oModel
 
/*/{Protheus.doc} ViewDef
Visualizacao de dados na funcao zTstPr2
@author Atilio
@since 11/01/2023
@version 1.0
@type function
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
/*/
 
Static Function ViewDef()
    Local oModel := FWLoadModel("zTstPr2")
    Local oStruPai := FWFormStruct(2, cTabPai)
    Local oStruFilho := FWFormStruct(2, cTabFilho)
    Local oView
    Local aChangeLine := {}
 
    aAdd(aChangeLine, bBlocoAtu)
 
    //Cria a visualizacao do cadastro
    oView := FWFormView():New()
    oView:SetModel(oModel)
    oView:AddField("VIEW_SBM", oStruPai, "SBMMASTER")
    oView:AddGrid("VIEW_SB1",  oStruFilho,  "SB1DETAIL")
    oView:AddOtherObject("VIEW_OTHER", {|oPanel| fCustom(oPanel)})
 
    //Definindo que irá mudar a cor da linha, e irá acionar para atualizar o totalizador ao alternar de linhas
    oView:SetViewProperty("VIEW_SB1", "SETCSS", {"QTableView { selection-background-color: #1C9DBD; selection-color: #FFFFFF; }"} )
    oView:SetViewProperty("VIEW_SB1", "CHANGELINE", aChangeLine)
 
    //Partes da tela
    oView:CreateHorizontalBox("CABEC", 30)
    oView:CreateHorizontalBox("GRID", 55)
    oView:CreateHorizontalBox("ENCH_TOT", 15)
    oView:SetOwnerView("VIEW_SBM", "CABEC")
    oView:SetOwnerView("VIEW_SB1", "GRID")
    oView:SetOwnerView("VIEW_OTHER", "ENCH_TOT")
 
    //Titulos
    oView:EnableTitleView("VIEW_SBM", "Cabecalho - SBM")
    oView:EnableTitleView("VIEW_SB1", "Grid - SB1")
    oView:EnableTitleView("VIEW_OTHER", "Totalizadores")
 
    //Removendo campos
    oStruFilho:RemoveField("B1_GRUPO")
 
Return oView
 
Static Function fCustom(oPanel)
    Local aArea       := FWGetArea()
    Local cFontNome   := "Tahoma"
    Local oFontPadrao := TFont():New(cFontNome, , -12)
    Local lDimPixels  := .T.
 
    //objeto2 - usando a classe TSay
    nObjLinha := 18
    nObjColun := 4
    nObjLargu := 45
    nObjAltur := 6
    oSayObj   := TSay():New(nObjLinha, nObjColun, {|| "Saldo Produto:"}, oPanel, /*cPicture*/, oFontPadrao, , , , lDimPixels, /*nClrText*/, /*nClrBack*/, nObjLargu, nObjAltur, , , , , , /*lHTML*/)
 
    //objeto3 - usando a classe TGet
    nObjLinha := 16
    nObjColun := 49
    nObjLargu := 100
    nObjAltur := 10
    oGetObj   := TGet():New(nObjLinha, nObjColun, {|| nSaldo}, oPanel, nObjLargu, nObjAltur, /*cPict*/, /*bValid*/, /*nClrFore*/, /*nClrBack*/, oFontPadrao, , , lDimPixels)
    oGetObj:lReadOnly  := .T.
 
    FWRestArea(aArea)
Return
 
/*/{Protheus.doc} User Function fAtualiza
Função que atualiza a troca de linhas e dispara uma ataulização no AddCalc
@type  Function
@author Atilio
@since 11/01/2023
/*/
 
Static Function fAtualiza()
    Local aArea    := FWGetArea()
    Local cProduto := ""
    Local cArmazem := ""
    Local dDataFim := sToD("")
    Local oGrid    := Nil
    Default oModel := FWModelActive()
 
    //Pega a grid e os totalizadores
    oGrid := oModel:GetModel("SB1DETAIL")
 
    //Define os parâmetros que serão usados no CalcEst
    cProduto := oGrid:GetValue("B1_COD")
    cArmazem := "01"
    dDataFim := DaySum(Date(), 1)
 
    //Busca os saldos
    aSaldos := CalcEst(cProduto, cArmazem, dDataFim)
 
    //Define o retorno
    nSaldo := aSaldos[1]
    If Type("oGetObj") != "U"
        oGetObj:Refresh()
    EndIf
 
    FWRestArea(aArea)
Return

Usando AddCalc (com inconsistência)

Exemplo utilizando AddCalc

//Bibliotecas
#Include "Totvs.ch"
#Include "FWMVCDef.ch"
 
//Variveis Estaticas
Static cTitulo := "Grupo x Produtos"
Static cTabPai := "SBM"
Static cTabFilho := "SB1"
 
/*/{Protheus.doc} User Function zTstPr1
Grupo x Produtos
@author Atilio
@since 11/01/2023
@version 1.0
@type function
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
/*/
 
User Function zTstPr1()
    Local aArea   := FWGetArea()
    Local oBrowse
    Private aRotina := {}
    Private bBlocoAtu := {|| fAtualiza()}
 
    //Definicao do menu
    aRotina := MenuDef()
 
    //Instanciando o browse
    oBrowse := FWMBrowse():New()
    oBrowse:SetAlias(cTabPai)
    oBrowse:SetDescription(cTitulo)
    oBrowse:DisableDetails()
 
    //Ativa a Browse
    oBrowse:Activate()
 
    FWRestArea(aArea)
Return Nil
 
/*/{Protheus.doc} MenuDef
Menu de opcoes na funcao zTstPr1
@author Atilio
@since 11/01/2023
@version 1.0
@type function
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
/*/
 
Static Function MenuDef()
    Local aRotina := {}
 
    //Adicionando opcoes do menu
    ADD OPTION aRotina TITLE "Visualizar" ACTION "VIEWDEF.zTstPr1" OPERATION 1 ACCESS 0
 
Return aRotina
 
/*/{Protheus.doc} ModelDef
Modelo de dados na funcao zTstPr1
@author Atilio
@since 11/01/2023
@version 1.0
@type function
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
/*/
 
Static Function ModelDef()
    Local oStruPai := FWFormStruct(1, cTabPai)
    Local oStruFilho := FWFormStruct(1, cTabFilho)
    Local aRelation := {}
    Local oModel
    Local bPre := bBlocoAtu
    Local bPos := Nil
    Local bCommit := Nil
    Local bCancel := Nil
 
 
    //Cria o modelo de dados para cadastro
    oModel := MPFormModel():New("zTstPr1M", bPre, bPos, bCommit, bCancel)
    oModel:AddFields("SBMMASTER", /*cOwner*/, oStruPai)
    oModel:AddGrid("SB1DETAIL","SBMMASTER",oStruFilho,/*bLinePre*/, /*bLinePost*/,/*bPre - Grid Inteiro*/,/*bPos - Grid Inteiro*/,/*bLoad - Carga do modelo manualmente*/)
    oModel:SetDescription("Modelo de dados - " + cTitulo)
    oModel:GetModel("SBMMASTER"):SetDescription( "Dados de - " + cTitulo)
    oModel:GetModel("SB1DETAIL"):SetDescription( "Grid de - " + cTitulo)
    oModel:SetPrimaryKey({})
 
    //Fazendo o relacionamento
    aAdd(aRelation, {"B1_FILIAL", "FWxFilial('SB1')"} )
    aAdd(aRelation, {"B1_GRUPO", "BM_GRUPO"})
    oModel:SetRelation("SB1DETAIL", aRelation, SB1->(IndexKey(1)))
 
    //Adicionando o totalizador
    oModel:AddCalc('TOTAIS', 'SBMMASTER', 'SB1DETAIL', 'B1_COD', 'XX_SALDO',  'FORMULA', {|| .T.}, /*bInitValue*/, "Saldo Produto: ", { |oModel| u_zSaldoTst(oModel)})
 
Return oModel
 
/*/{Protheus.doc} ViewDef
Visualizacao de dados na funcao zTstPr1
@author Atilio
@since 11/01/2023
@version 1.0
@type function
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
/*/
 
Static Function ViewDef()
    Local oModel := FWLoadModel("zTstPr1")
    Local oStruPai := FWFormStruct(2, cTabPai)
    Local oStruFilho := FWFormStruct(2, cTabFilho)
    Local oStruTot := FWCalcStruct(oModel:GetModel('TOTAIS'))
    Local oView
    Local aChangeLine := {}
 
    aAdd(aChangeLine, bBlocoAtu)
 
    //Cria a visualizacao do cadastro
    oView := FWFormView():New()
    oView:SetModel(oModel)
    oView:AddField("VIEW_SBM", oStruPai, "SBMMASTER")
    oView:AddGrid("VIEW_SB1",  oStruFilho,  "SB1DETAIL")
    oView:AddField("VIEW_TOT", oStruTot,   "TOTAIS")
 
    //Definindo que irá mudar a cor da linha, e irá acionar para atualizar o totalizador ao alternar de linhas
    oView:SetViewProperty("VIEW_SB1", "SETCSS", {"QTableView { selection-background-color: #1C9DBD; selection-color: #FFFFFF; }"} )
    oView:SetViewProperty("VIEW_SB1", "CHANGELINE", aChangeLine)
 
    //Partes da tela
    oView:CreateHorizontalBox("CABEC", 30)
    oView:CreateHorizontalBox("GRID", 55)
    oView:CreateHorizontalBox("ENCH_TOT", 15)
    oView:SetOwnerView("VIEW_SBM", "CABEC")
    oView:SetOwnerView("VIEW_SB1", "GRID")
    oView:SetOwnerView("VIEW_TOT", "ENCH_TOT")
 
    //Titulos
    oView:EnableTitleView("VIEW_SBM", "Cabecalho - SBM")
    oView:EnableTitleView("VIEW_SB1", "Grid - SB1")
    oView:EnableTitleView("VIEW_TOT", "Totalizadores")
 
    //Removendo campos
    oStruFilho:RemoveField("B1_GRUPO")
 
Return oView
 
/*/{Protheus.doc} User Function zSaldoTst
Função que atualiza o totalizador do AddCalc
@type  Function
@author Atilio
@since 11/01/2023
/*/
 
User Function zSaldoTst(oModel)
    Local aArea    := FWGetArea()
    Local nSaldo   := 0
    Local cProduto := ""
    Local cArmazem := ""
    Local dDataFim := sToD("")
    Local oGrid    := Nil
    Default oModel := FWModelActive()
 
    //Pega a grid e os totalizadores
    oGrid := oModel:GetModel("SB1DETAIL")
    oTot  := oModel:GetModel("TOTAIS")
 
    //Define os parâmetros que serão usados no CalcEst
    cProduto := oGrid:GetValue("B1_COD")
    cArmazem := "01"
    dDataFim := DaySum(Date(), 1)
 
    //Busca os saldos
    aSaldos := CalcEst(cProduto, cArmazem, dDataFim)
 
    //Define o retorno
    nSaldo := aSaldos[1]
 
    FWRestArea(aArea)
Return nSaldo
 
/*/{Protheus.doc} User Function fAtualiza
Função que atualiza a troca de linhas e dispara uma ataulização no AddCalc
@type  Function
@author Atilio
@since 11/01/2023
/*/
 
Static Function fAtualiza()
    oModel := FWModelActive()
    oTot  := oModel:GetModel("TOTAIS")
    oTot:SetValue("XX_SALDO", 0)
Return

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.

Deixe uma resposta

Terminal de Informação