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

