Estou implementando o ponto de entrada CTBA020 em MVC, e utilizando o ponto de execução ‘MODELCOMMITNTTS’, para replicar uma conta após a sua gravação, contudo no momento da gravação utilizando a função “CommitData()” e chamado novamente o ponto de entrada CTBA020, o que ocasiona uma recursividade, um loop, que somente e interrompido quando a rotina tenta gravar uma conta que já existe e ocorre um erro na função VldData().
Tentei de diversas formas, mas não consegui solucionar esse problema, alguém tem alguma solução.
@Marcio_Seiji não deveria executar novamente o Commit dentro do ponto de entrada, por isso está entrando em recursividade. Descreve melhor o que você precisa fazer ou posta o fonte aqui para gente analisar.
Olá Marcio, complicada essa situação ai, talvez se você desacoplar sua função em outra e verificar com FwIsInCallStack se ela foi executada resolva seu problema.
Se não der certo, usao PE FORMCOMMITTTSPOS que é após o commit
User Function CTBA020
if !FwIsInCallStack(“u_fCTBA020”)
fCTBA020()
endif
User Function fCTBA020()
//comita aqui
return
Um exemplo…
User Function CTAB020()
.
.
.
If aParam <> NIL
oObj := aParam[1]
cIdPonto := aParam[2]
cIdModel := aParam[3]
lIsGrid := (Len(aParam) > 3)
nOpcAuto := oObj:GetOperation()
If cIdPonto == "MODELCOMMITNTTS"
Replica(nOpcAuto)
EndIf
EndIf
Return xRet
Static Function Replica(nOpcAuto)
Local oModelAut := NIL
Local cFilBkp := cFilAnt
If oModelAut == Nil //somente uma unica vez carrega o modelo CTBA020-Plano de Contas CT1
oModelAut := FWLoadModel('CTBA020')
EndIf
oModelAut:Activate() //ativa modelo
Do Case
Case nOpcAuto == 3 //Inclusao
cFilAnt := "12"
//Preencho os valores da CT1
oCT1 := oModelAut:GetModel('CT1MASTER') //Objeto similar enchoice CT1
oCT1:SETVALUE('CT1_FILIAL',cFilAnt)
oCT1:SETVALUE('CT1_CONTA' ,"0000001")
oCT1:SETVALUE('CT1_DESC01',"TESTE")
oCT1:SETVALUE('CT1_CLASSE',"2")
oCT1:SETVALUE('CT1_NORMAL',"1")
//Valido e gravo
If oModel:VldData() //Ocorre recursividade volta para CTA020
oModel:CommitData() //ocorre recursividade volta para CTA020
MsgInfo("Registro INCLUIDO!", "Atenção")
Else
VarInfo("",oModel:GetErrorMessage()) //Somente sai quando entra no erro
EndIf
cFilBkp := cFilAnt
EndCase
oModelAut:DeActivate() //desativa modelo
Return
@Marcio_Seiji boa tarde.
Eu fiz isso com outros cadastro na folha de pagamento, utilizando Reclock nesses mesmo ponto de entrada. Fiz um reclock dinâmico que busca a estrutura da tabela.
Leandro,
Testei o PE FORMCOMMITTTSPOS, como sugerido, mas ainda assim entra na recursividade.
@Marcio_Seiji explica melhor o que esta fazendo nesse ponto de entrada, está incluindo novas contas baseado na atual ? Não precisaria chamar o commit dentro do ponto de entrada, ele já faz isso sozinho.
Olá.
Se a réplica deve ser realizada apenas uma vez, você pode fazer um controle da stack para não replicar mais de uma vez, utilizando a função FwIsInCallStack. Exemplo:
If(cIdPonto == "MODELCOMMITNTTS")
If(!FwIsInCallStack('Replica')) // Se já estiver em um processo de replicação, não entra
Replica(nOpcAuto)
EndIf
EndIf
Dessa forma, a função “Replica” será chamada apenas uma vez, para replicar o cadastro original em outro. Quando o ponto de entrada for chamado a segunda vez, ele não irá chamar a função “Replica” novamente pois ela já está no stack.
Documentação: FWIsInCallStack - Frameworksp - TDN
Estou replicando o cadastro de contas contábeis para as outras filiais do sistema, tabela CT1 (compartilha).
Felipe, boa noite.
Eh, pensei em fazer isso, alias ainda estou pensando, caso não consiga resolver a recursividade de outra forma, pelo menos para entregar a funcionalidade, depois com mais tempo analiso isso melhor.
Mas gostaria de tentar resolver isso… antes de me dar por vencido…
Boa noite.
Sobre a função FWIsInCallStack, e uma boa ideia.
Vou implementar e testar para ver como isso funciona.
Obrigado.
Então a solução é mesmo identificar pela pilha de chamadas se já está vindo de um processo de réplica e então não executar novamente. E nesse caso o ponto ideal é o fora da transação após as gravações FORMCOMMITTTSPOS .