Olá pessoal…
Hoje vou mostrar uma rotina que desenvolvi para cadastro de parâmetros (SX6) no Protheus, similar ao AxCadastro ou a mBrowse.
O intuito dessa rotina, é liberar o cadastro de parâmetros aos usuários, porém ressalto, que o ideal é liberar apenas acesso à parâmetros customizados.
A rotina, ela recebe 3 parâmetros para a montagem da tela, o primeiro, são os parâmetros que estarão disponíveis para cadastro (ou seja, mesmo que o usuário tente digitar outro parâmetro, só serão aceitos os que estiverem nesse array). O segundo parâmetro, é se o cadastro de parâmetros irá utilizar combo (com a listagem de parâmetros conforme array), ou se será usado um get. O último parâmetro, define se será possível excluir o registro.
A tela principal, mostra a listagem de parâmetros.
Ao clicar em Incluir, é necessário informar todos os campos (somente a filial que não é obrigatória), e o RecNO não pode ser preenchido.
Ao clicar em Alterar, somente é possível, alterar o conteúdo e a descrição, os outros campos são bloqueados para edição.
Abaixo o código fonte utilizado.
//Bibliotecas #Include "Protheus.ch" //Constantes #Define CLR_AZUL RGB(058,074,119) //Cor Azul //Variaveis Static COL_T1 := 001 //Primeira Coluna da tela Static COL_T2 := 123 //Segunda Coluna da tela Static COL_T3 := 245 //Terceira Coluna da tela Static COL_T4 := 367 //Quarta Coluna da tela Static ESP_CAMPO := 038 //Espaçamento do campo para coluna Static TAM_FILIAL := FWSizeFilial() //Tamanho do campo Filial /*/{Protheus.doc} zCadSX6 Lista parâmetros ao usuário com as opções de incluir, alterar e excluir @author Atilio @since 14/11/2014 @version 1.0 @param aParams, Array, Parâmetros que serão listados ao usuário para edição @param lCombo, Lógico, Define se os parâmetros serão mostrados em combo quando houver inclusão @param lDelet, Lógico, Define se será possível a exclusão de parâmetros @example aParams := { "MV_X_AMBOF","MV_X_USERS"} u_zCadSX6(aParams, .T., .T.) /*/ User Function zCadSX6(aParams, lCombo, lDelet) Local aArea := GetArea() Local aAreaX6 := SX6->(GetArea()) Local nAtual := 0 Local nColuna := 6 Default lCombo := .T. Default lDelet := .F. Default aParams := {} Private lComboPvt := lCombo Private aParamsPvt := {} Private cParamsPvt := "" //Tamanho da Janela Private aTamanho := MsAdvSize() Private nJanLarg := aTamanho[5] Private nJanAltu := aTamanho[6] Private nColMeio := (nJanLarg)/4 Private nEspCols := ((nJanLarg/2)-12)/4 COL_T1 := 003 COL_T2 := COL_T1+nEspCols COL_T3 := COL_T2+nEspCols COL_T4 := COL_T3+nEspCOls //Objetos gráficos Private oDlgSX6 //GetDados Private oMsGet Private aHeader := {} Private aCols := {} //Botões Private aButtons := {} aAdd(aButtons,{"Incluir", "{|| fInclui()}", "oBtnInclui"}) aAdd(aButtons,{"Alterar", "{|| fAltera()}", "oBtnAltera"}) aAdd(aButtons,{"Visualizar", "{|| fVisualiza()}", "oBtnVisual"}) If lDelet aAdd(aButtons,{"Excluir", "{|| fExclui()}", "oBtnExclui"}) EndIf aAdd(aButtons,{"Sair", "{|| oDlgSX6:End()}", "oBtnSair"}) //Se não tiver parâmetros If Len(aParams) <= 0 MsgStop("Parâmetros devem ser informados!", "Atenção") Return Else aParamsPvt := aParams cParamsPvt := "" //Percorrendo os parâmetros e adicionando For nAtual := 1 To Len(aParamsPvt) cParamsPvt += aParamsPvt[nAtual]+";" Next EndIf //Adicionando cabeçalho aAdd(aHeader,{"Filial", "ZZ_FILIAL", "@!", TAM_FILIAL, 0, ".F.", ".F.", "C", "", "" ,}) aAdd(aHeader,{"Parâmetro", "ZZ_PARAME", "@!", 010, 0, ".F.", ".F.", "C", "", "" ,}) aAdd(aHeader,{"Tipo", "ZZ_TIPO", "@!", 001, 0, ".F.", ".F.", "C", "", "" ,}) aAdd(aHeader,{"Descrição", "ZZ_DESCRI", "@!", 150, 0, ".F.", ".F.", "C", "", "" ,}) aAdd(aHeader,{"Conteúdo", "ZZ_CONTEU", "@!", 250, 0, ".F.", ".F.", "C", "", "" ,}) aAdd(aHeader,{"RecNo", "ZZ_RECNUM", "", 018, 0, ".F.", ".F.", "N", "", "" ,}) //Atualizando o aCols fAtuaCols(.T.) //Criando a janela DEFINE MSDIALOG oDlgSX6 TITLE "Parâmetros:" FROM 000, 000 TO nJanAltu, nJanLarg COLORS 0, 16777215 PIXEL oMsGet := MsNewGetDados():New( 3,; //nTop 3,; //nLeft (nJanAltu/2)-33,; //nBottom (nJanLarg/2)-3,; //nRight GD_INSERT+GD_DELETE+GD_UPDATE,; //nStyle "AllwaysTrue()",; //cLinhaOk ,; //cTudoOk "",; //cIniCpos ,; //aAlter ,; //nFreeze 999999,; //nMax ,; //cFieldOK ,; //cSuperDel ,; //cDelOk oDlgSX6,; //oWnd aHeader,; //aHeader aCols) //aCols oMsGet:lActive := .F. //Grupo Legenda @ (nJanAltu/2)-30, 003 GROUP oGrpLeg TO (nJanAltu/2)-3, (nJanLarg/2)-3 PROMPT "Ações: " OF oDlgSX6 COLOR 0, 16777215 PIXEL //Adicionando botões For nAtual := 1 To Len(aButtons) @ (nJanAltu/2)-20, nColuna BUTTON &(aButtons[nAtual][3]) PROMPT aButtons[nAtual][1] SIZE 60, 014 OF oDlgSX6 PIXEL (&(aButtons[nAtual][3]+":bAction := "+aButtons[nAtual][2])) nColuna += 63 Next ACTIVATE MSDIALOG oDlgSX6 CENTERED RestArea(aAreaX6) RestArea(aArea) Return /*---------------------------------------------------------------------* | Func: fInclui | | Autor: Daniel Atilio | | Data: 14/11/2014 | | Desc: Função de inclusão de parâmetro | | Obs.: / | *---------------------------------------------------------------------*/ Static Function fInclui() Local nAtual := oMsGet:nAt Local aColsAux := oMsGet:aCols Local nPosRecNo:= aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_RECNUM" }) fMontaTela(3, 0) Return /*---------------------------------------------------------------------* | Func: fAltera | | Autor: Daniel Atilio | | Data: 14/11/2014 | | Desc: Função de alteração de parâmetro | | Obs.: / | *---------------------------------------------------------------------*/ Static Function fAltera() Local nAtual := oMsGet:nAt Local aColsAux := oMsGet:aCols Local nPosRecNo:= aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_RECNUM" }) //Se tiver recno válido If aColsAux[nAtual][nPosRecNo] != 0 fMontaTela(4, aColsAux[nAtual][nPosRecNo]) EndIf Return /*---------------------------------------------------------------------* | Func: fExclui | | Autor: Daniel Atilio | | Data: 14/11/2014 | | Desc: Função de exclusão de parâmetro | | Obs.: / | *---------------------------------------------------------------------*/ Static Function fExclui() Local nAtual := oMsGet:nAt Local aColsAux := oMsGet:aCols Local nPosRecNo:= aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_RECNUM" }) //Se tiver recno válido If aColsAux[nAtual][nPosRecNo] != 0 fMontaTela(5, aColsAux[nAtual][nPosRecNo]) EndIf Return /*---------------------------------------------------------------------* | Func: fVisualiza | | Autor: Daniel Atilio | | Data: 14/11/2014 | | Desc: Função de visualização de parâmetro | | Obs.: / | *---------------------------------------------------------------------*/ Static Function fVisualiza() Local nAtual := oMsGet:nAt Local aColsAux := oMsGet:aCols Local nPosRecNo:= aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_RECNUM" }) //Se tiver recno válido If aColsAux[nAtual][nPosRecNo] != 0 fMontaTela(2, aColsAux[nAtual][nPosRecNo]) EndIf Return /*---------------------------------------------------------------------* | Func: fAtuaCols | | Autor: Daniel Atilio | | Data: 14/11/2014 | | Desc: Função que atualiza o aCols com os parâmetros | | Obs.: Como a intenção é ter poucos parâmetros, sempre ele irá | | percorrer a SX6 e adicionar no aCols | *---------------------------------------------------------------------*/ Static Function fAtuaCols(lFirst) Local aAreaSX6 := SX6->(GetArea()) aCols := {} //Selecionando a tabela de parâmetros e indo ao topo DbSelectArea("SX6") SX6->(DbGoTop()) //Percorrendo os parâmetros, e adicionando somente os que estão na filtragem While !SX6->(EoF()) If Alltrim(SX6->X6_VAR) $ cParamsPvt aAdd( aCols, { SX6->X6_FIL,; //Filial SX6->X6_VAR,; //Parâmetro SX6->X6_TIPO,; //Tipo SX6->X6_DESCRIC+SX6->X6_DESC1+SX6->X6_DESC2,; //Descrição SX6->X6_CONTEUD,; //Conteúdo SX6->(RecNo()),; //RecNo .F.}) //Excluído? EndIf SX6->(DbSkip()) EndDo //Se tiver zerada, adiciona conteúdo em branco If Len(aCols) == 0 aAdd( aCols, { "",; //Filial "",; //Parâmetro "",; //Tipo "",; //Descrição "",; //Conteúdo 0,; //RecNo .F.}) //Excluído? EndIf //Senão for a primeira vez, atualiza grid If !lFirst oMsGet:setArray(aCols) EndIf RestArea(aAreaSX6) Return /*---------------------------------------------------------------------* | Func: fMontaTela | | Autor: Daniel Atilio | | Data: 14/11/2014 | | Desc: Função que atualiza o aCols com os parâmetros | | Obs.: / | *---------------------------------------------------------------------*/ Static Function fMontaTela(nOpcP, nRecP) Local nColuna := 6 Local nEsp := 15 Private nOpcPvt := nOpcP Private nRecPvt := nRecP Private aOpcTip := {" ", "C - Caracter", "N - Numérico", "L - Lógico", "D - Data", "M - Memo"} Private oFontNeg := TFont():New("Tahoma") Private oDlgEdit //Campos Private oGetFil, cGetFil Private oGetPar, cGetPar Private oGetTip, cGetTip Private oGetDes, cGetDes Private oGetCon, cGetCon Private oGetRec, nGetRec //Botões Private aBtnPar := {} aAdd(aBtnPar,{"Confirmar", "{|| fBtnEdit(1)}", "oBtnConf"}) aAdd(aBtnPar,{"Cancelar", "{|| fBtnEdit(2)}", "oBtnCanc"}) //Se não for inclusão, pega os campos conforme array If nOpcP != 3 aColsAux := oMsGet:aCols nLinAtu := oMsGet:nAt nPosFil := aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_FILIAL" }) nPosPar := aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_PARAME" }) nPosTip := aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_TIPO" }) nPosDes := aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_DESCRI" }) nPosCon := aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_CONTEU" }) nPosRec := aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_RECNUM" }) //Atualizando gets cGetFil := aColsAux[nLinAtu][nPosFil] cGetPar := aColsAux[nLinAtu][nPosPar] cGetTip := aColsAux[nLinAtu][nPosTip] cGetDes := aColsAux[nLinAtu][nPosDes] cGetCon := aColsAux[nLinAtu][nPosCon] nGetRec := aColsAux[nLinAtu][nPosRec] //Caracter If cGetTip == "C" cGetTip := aOpcTip[2] //Numérico ElseIf cGetTip == "N" cGetTip := aOpcTip[3] //Lógico ElseIf cGetTip == "L" cGetTip := aOpcTip[4] //Data ElseIf cGetTip == "D" cGetTip := aOpcTip[5] //Memo ElseIf cGetTip == "M" cGetTip := aOpcTip[6] EndIf //Senão, deixa os campos zerados Else //Atualizando gets cGetFil := Space(TAM_FILIAL) cGetPar := Space(010) cGetTip := aOpcTip[1] cGetDes := Space(150) cGetCon := Space(250) nGetRec := 0 EndIf oFontNeg:Bold := .T. //Criando a janela DEFINE MSDIALOG oDlgEdit TITLE "Dados:" FROM 000, 000 TO nJanAltu, nJanLarg COLORS 0, 16777215 PIXEL nLinAux := 6 //Filial @ nLinAux , COL_T1 SAY oSayFil PROMPT "Filial:" SIZE 040, 007 OF oDlgEdit COLORS CLR_AZUL PIXEL @ nLinAux-003, COL_T1+ESP_CAMPO MSGET oGetFil VAR cGetFil SIZE 060, 010 OF oDlgEdit COLORS 0, 16777215 PIXEL //Parâmetro @ nLinAux , COL_T2 SAY oSayPar PROMPT "Parâmetro:" SIZE 040, 007 OF oDlgEdit COLORS CLR_AZUL FONT oFontNeg PIXEL If lComboPvt @ nLinAux-003, COL_T2+ESP_CAMPO MSCOMBOBOX oGetPar VAR cGetPar ITEMS aParamsPvt SIZE 060, 010 OF oDlgEdit COLORS 0, 16777215 PIXEL Else @ nLinAux-003, COL_T2+ESP_CAMPO MSGET oGetPar VAR cGetPar SIZE 060, 010 OF oDlgEdit COLORS 0, 16777215 VALID (cGetPar $ cParamsPvt) PIXEL EndIf //Tipo @ nLinAux , COL_T3 SAY oSayTip PROMPT "Tipo:" SIZE 040, 007 OF oDlgEdit COLORS CLR_AZUL FONT oFontNeg PIXEL @ nLinAux-003, COL_T3+ESP_CAMPO MSCOMBOBOX oGetTip VAR cGetTip ITEMS aOpcTip SIZE 060, 010 OF oDlgEdit COLORS 0, 16777215 PIXEL //RecNo @ nLinAux , COL_T4 SAY oSayRec PROMPT "RecNo:" SIZE 040, 007 OF oDlgEdit COLORS CLR_AZUL PIXEL @ nLinAux-003, COL_T4+ESP_CAMPO MSGET oGetRec VAR nGetRec SIZE 060, 010 OF oDlgEdit COLORS 0, 16777215 PIXEL nLinAux += nEsp //Descrição @ nLinAux , COL_T1 SAY oSayDes PROMPT "Descrição:" SIZE 040, 007 OF oDlgEdit COLORS CLR_AZUL FONT oFontNeg PIXEL @ nLinAux-003, COL_T1+ESP_CAMPO MSGET oGetDes VAR cGetDes SIZE 300, 010 OF oDlgEdit COLORS 0, 16777215 PIXEL nLinAux += nEsp //Conteúdo @ nLinAux , COL_T1 SAY oSayCon PROMPT "Conteúdo:" SIZE 040, 007 OF oDlgEdit COLORS CLR_AZUL FONT oFontNeg PIXEL @ nLinAux-003, COL_T1+ESP_CAMPO MSGET oGetCon VAR cGetCon SIZE 300, 010 OF oDlgEdit COLORS 0, 16777215 PIXEL //Grupo Legenda @ (nJanAltu/2)-30, 003 GROUP oGrpLegEdit TO (nJanAltu/2)-3, (nJanLarg/2)-3 PROMPT "Ações (Confirmação): " OF oDlgEdit COLOR 0, 16777215 PIXEL //Adicionando botões For nAtual := 1 To Len(aBtnPar) @ (nJanAltu/2)-20, nColuna BUTTON &(aBtnPar[nAtual][3]) PROMPT aBtnPar[nAtual][1] SIZE 60, 014 OF oDlgEdit PIXEL (&(aBtnPar[nAtual][3]+":bAction := "+aBtnPar[nAtual][2])) nColuna += 63 Next //Se for visualização ou exclusão, todos os gets serão desabilitados If nOpcP == 2 .Or. nOpcP == 5 oGetFil:lActive := .F. oGetPar:lActive := .F. oGetTip:lActive := .F. oGetDes:lActive := .F. oGetCon:lActive := .F. Else //Se for alteração, desabilita a Filial, Parâmetro e Tipo If nOpcP == 4 oGetFil:lActive := .F. oGetPar:lActive := .F. oGetTip:lActive := .F. EndIf EndIf //Campo de RecNo sempre será desabilitado oGetRec:lActive := .F. ACTIVATE MSDIALOG oDlgEdit CENTERED Return /*---------------------------------------------------------------------* | Func: fBtnEdit | | Autor: Daniel Atilio | | Data: 16/12/2014 | | Desc: Função que confirma a tela | | Obs.: / | *---------------------------------------------------------------------*/ Static Function fBtnEdit(nConf) Local aAreaAux := GetArea() //Se for o Cancelar If nConf == 2 oDlgEdit:End() //Se for o Confirmar ElseIf nConf == 1 //Se for visualizar If nOpcPvt == 2 oDlgEdit:End() //Senão for visualizar Else //Se for exclusão If nOpcPvT == 5 SX6->(DbGoTo(nRecPvt)) RecLock("SX6", .F.) DbDelete() SX6->(MsUnlock()) oDlgEdit:End() Else //Descrição ou conteúdo em branco? If Empty(cGetDes) .Or. Empty(cGetCon) If !MsgYesNo("O campo <b>Descrição</b> e/ou <b>Conteúdo</b> estão com conteúdo em branco!<br>Deseja continuar?", "Atenção") Return EndIf EndIf //Se for inclusão If nOpcPvt == 3 //Tipo e parâmetro em branco? If Empty(cGetTip) .Or. Empty(cGetPar) MsgAlert("O campo <b>Parâmetro</b> e/ou <b>Tipo</b> estão com conteúdo em branco!", "Atenção") Return EndIf //Já existe registro? SX6->(DbGoTop()) If (SX6->(DbSeek(cGetFil+cGetPar))) MsgAlert("Filial e Parâmetro já existem!", "Atenção") Return EndIf //Travando tabela para inclusão RecLock("SX6", .T.) X6_FIL := cGetFil X6_VAR := cGetPar X6_TIPO := cGetTip //Se for alteração, trava tabela para alteração ElseIf nOpcPvt == 4 SX6->(DbGoTo(nRecPvt)) RecLock("SX6", .F.) EndIf //Gravando informações X6_DESCRIC := SubStr(cGetDes,001,50) X6_DESC1 := SubStr(cGetDes,051,50) X6_DESC2 := SubStr(cGetDes,101,50) X6_CONTEUD := cGetCon SX6->(MsUnlock()) oDlgEdit:End() EndIf EndIf //Atualizando a grid fAtuaCols(.F.) EndIf RestArea(aAreaAux) Return
Bom pessoal, por hoje é só.
Abraços e até a próxima.
Olá Dan, espero que tudo bem. Primeiramente parabéns pelos seus artigos …! 🙂
Eu preciso somente de permitir alteração de parâmetro para prorrogar prazo para cancelamento de NF´s
AlteraR o parâmetro MV_SPEDEXC. DE 24 PARA X HORAS (48,72, 96 …)
AlteraR o parâmetro MV_CANCEXT de 5 para 7 dias….
Eu localizei um artigo da UserFunction (E PEDI O FONTE POR E-MAIL) baseado neste seu que sugere esta parte de permitir somente algum
parâmetro específico (segue para conhecimento):
https://userfunction.com.br/infraestrutura/sigacfg/protheus_tela_parametros/#wpcf7-f659-p10096-o1
Apresenta estas mensagens na compilação:
W0003 Local variable NATUAL never used
W0003 Local variable ACOLSAUX never used
W0003 Local variable NPOSRECNO never used
W0004 For variable is not Local. This warning may be an error in future version.
Eu PRETENDO tentar assim:
User Function AltMVHORAS()
u_zCadSX6({“MV_SPEDEXC”}, .t., .f.)
Return
User Function AltMVDIAS()
u_zCadSX6({” MV_CANCEXT”}, .t., .f.)
Return
Porém no seu fonte antes de começar a mexer eu simplesmente copiei e colei o seu fonte e compilei (obs.: No VSCode) e já apresentou mensagem abaixo:
variable is not Local
[{
“resource”: “/D:/Alan Rigueto/Documentos/Protheus/Projetos/Faturamento/zCadSX6.prw”,
“owner”: “AdvPL”,
“severity”: 8,
“message”: “variable is not Local”,
“source”: “Linter”,
“startLineNumber”: 358,
“startColumn”: 1,
“endLineNumber”: 359,
“endColumn”: 1
}]
Por favor orientar como corrigir e se não for pedir muito um fonte “exemplo” somente com opção de alteração, não de criação e exclusão de parâmetros
Desde já agradeço
Abs.
Att.
Atualizando o post anterior:
Olá,
A princípio ao compilar o fonte sem alterar nada (Obs.: Via VScode) estava apresentando mensagem:
warning W0004 For variable is not Local
Consultando solução localizei a sugestão:
A variável utilizada no For, não foi declarada localmente, é necessário declarar ela
Nota.: No fonte já está declarada na User Function Local nAtual := 0, conforme trecho do fonte original abaixo:
User Function zCadSX6(aParams, lCombo, lDelet)
Local aArea := GetArea()
Local aAreaX6 := SX6->(GetArea())
Local nAtual := 0
Mesmo assim declarei Local nAtual neste trecho da função “MontaTela”:
Static Function fMontaTela(nOpcP, nRecP)
//nAtual := 1 ou 0 ou Local nAtual := oMsGet:nAt ?
Local nColuna := 6
Local nEsp := 15
Local nAtual
E a partir dai pelo menos compilou porém quando chamo a função zCadSX6 já na aplicação do Protheus apresenta mensagem:
”
Parâmetros devem ser informados
”
Já tentei declarar destas 3 formas:
Local nAtual := 1
Local nAtual := 0
Local nAtual := oMsGet:nAt
O que seria o corrreto?
Aguardo orientações
Desde já agradeço
Abs.
Att.
Bom dia Alan, tudo joia?
Certo, vamos lá, primeiro sobre os warnings / errors, os que tiverem “variable never used”, você pode comentar a linha de declaração. Já o For variable is not local, você declara a variável usada no for dentro da function como Local.
Como esse é um fonte antigo (de 2014), faz tempo que não reviso ele, ainda mais que nas versões mais novas do Protheus, a manipulação do dicionário não é mais recomendada.
Agora, para acionar a função, você deve fazer da seguinte forma:
Pois se você acionar direto a função, vai ocasionar a mensagem “Parâmetros devem ser informados”, por isso que acima nós passamos um array com o nome dos parâmetros da SX6.
Deixo ainda uma sugestão, caso você já queira fazer um código que não use a manipulação direta do dicionário, crie uma função que use PutMV, por exemplo:
Ai, basta você acionar essa sua zFuncao, que irá aparecer uma tela para digitar o valor do parâmetro.
Q bom, tdo joia tbém
Opa, já testei aqui no ambiente de validação e funcionou o parâmetro MV_SPEDEXC. DE 24 PARA X HORAS (48,72, 96 …)
Vou fazer mais alguns ajustes, e seguir a mesma lógica também para o parâmetro MV_CANCEXT de 5 para X dias …
para colocar em PROD
Valew
Opa, fico feliz em ter ajudado.
Abraços.
Lega. Muito obrigado. Funcionou certinho!
Dan, aproveitando você tem algo para atender Endereçamento de Produto:
Objeto: MATA265
NECESSIDADE:
EXIBIR AVISO QUANDO TENTAR ENDERECAR PRODUTO QUE JA EXISTE EM OUTRO ENDERECO
USER FUNCTION (abaixo) COMPILADA no ambiente validacão no projeto Estoque atualizações
MAS NÃO SURTIU EFEITO
Acredito que seja algo neste sentido:
”
User Function vldProd()
Local lReturn := .F.
Local aArea := GetArea()
Local cEndereco := IIF( AllTrim(Upper(ReadVar())) == “M->DB_LOCALIZ”, &(ReadVar()), GdFieldGet(“DB_LOCALIZ”) ) // Descubro se a funcao foi chamada via interface, ou se devo buscar o produto na linha do Grid
Local cSeek
dbSelectArea(“SBF”)
SBF->( dbSetOrder(1) )
cSeek:=xFilial(“SBF”)+ cEndereco+SDA->DA_LOCAL+SDA->DA_PRODUTO
If SBF->( dbSeek(cSeek) )
Alert(“Produto ” + SDA->DA_PRODUTO + ” encontrado no endereço ” + cEndereco)
Else
EndIf
RestArea(aArea)
Return (lReturn)
”
Desde já agradeço
Até
Abs.
Att.
Nunca precisei fazer algo nesse sentido Alan.
Essa função vldProd, você está acionando na validação de usuário ao digitar o campo produto ou em um ponto de entrada?
Pois aparentemente parece que a lógica está correta mesmo, olhando por cima (o que eu recomendaria seria usar FWxFilial, FWGetArea, FWRestARea e MsSeek no lugar das funções que vocês esta usando, além de ter um else sem nenhum comando dentro).
Bom dia Daniel, tudo bem? Ao passar pelo CodeAnalysis esse fonte gera o erro: Direct Access not allowed in data dictionary., Você compatibilizou este fonte para o dicionário de dados depois da migração para o banco de dados?
Boa tarde Paulo, tudo joia graças a Deus e você?
Eu não compatibilizei, na verdade eu descontinuei esse código, pois a TOTVS não permite mais a manipulação de dicionário diretamente devido as diretivas de boas práticas.
Caso você deseja alterar parâmetros, ainda existe a PutMV – https://tdn.totvs.com/pages/releaseview.action?pageId=22479602
Obrigado pelo retorno Daniel, o fonte era muito bom, o putmv é por filial desta forma quando o parâmetro é exclusivo é mais operacional mas tem que se adaptar as novas regras.
Opa eu que agradeço pelo feedback Paulo.
Sim, ajudava bem né.
Um grande abraço.