Função para deixar o código do produto sequencial conforme o grupo

Olá pessoal…

Hoje vou mostrar para vocês uma função rápida e fácil para preenchimento inteligente do código do produto no Protheus.

Muitas vezes as empresas querem ter um código sequencial de produto inteligente, e pensando nisso montei esse tutorial com um roteiro, sendo que aqui, o código vai se basear no Grupo do Produto + Sequencial do Produto. Basta seguir esses passos:

1. Acesse o Configurador (SIGACFG), vá na tabela SB1 e clique em Editar
2. Vá no campo Grupo (B1_GRUPO), verifique se ele está como obrigatório, caso não esteja, deixe ele como obrigatório (está na aba Uso)
3. No modo de edição do campo, deixe a expressão INCLUI para ele ficar habilitado apenas na inclusão (está na aba Opções)

Modo de Edição do campo Grupo

Modo de Edição do campo Grupo

4. Altere a sequência do campo, para ele vir antes do campo Código (B1_COD)
5. Vá no campo Código (B1_COD), no modo de edição deixe a expressão .F. para não deixar alterar o campo
6. Confirme as alterações da tabela
7. Vá na seção de Gatilhos, e clique para incluir um novo Gatilho. Nesse Gatilho, coloque a origem sendo o B1_GRUPO, e o destino o B1_COD, e a Regra sendo u_zGrupCod()

Criação do Gatilho

Criação do Gatilho

8. Salve as alterações do Configurador
9. Compile a função abaixo

//Bibliotecas
#Include "Protheus.ch"
#Include "TopConn.ch"

/*/{Protheus.doc} zGrupCod
Função que preenche o código do produto conforme o grupo
@author Atilio
@since 04/04/2018
@version 1.0
@type function
@obs Passo a Passo de como fazer para funcionar:
	1. Acesse o Configurador (SIGACFG), vá na tabela SB1 e clique em Editar
	2. Vá no campo Grupo (B1_GRUPO), verifique se ele está como obrigatório, caso não esteja, deixe ele como obrigatório (está na aba Uso)
	3. No modo de edição do campo, deixe a expressão INCLUI para ele ficar habilitado apenas na inclusão (está na aba Opções)
	4. Altere a sequência do campo, para ele vir antes do campo Código (B1_COD)
	5. Vá no campo Código (B1_COD), no modo de edição deixe a expressão .F. para não deixar alterar o campo
	6. Confirme as alterações da tabela
	7. Vá na seção de Gatilhos, e clique para incluir um novo Gatilho. Nesse Gatilho, coloque a origem sendo o B1_GRUPO, e o destino o B1_COD, e a Regra sendo <b>u_zGrupCod()</b>
	8. Salve as alterações do Configurador
	9. Compile a função abaixo
/*/

User Function zGrupCod()
	Local aArea   := GetArea()
	Local cCodigo := ""
	Local cGrupo  := FWFldGet("B1_GRUPO")
	Local cQryAux := ""
	Local nTamGrp := TamSX3('B1_GRUPO')[01]
	Local nTamCod := TamSX3('B1_COD')[01]
	
	//Se houver grupo
	If ! Empty(cGrupo)
		cCodigo := cGrupo + Replicate('0', nTamCod-nTamGrp)
		
		//Pegando o último código (não foi fitraldo o DELET para manter a sequencia unica)
		cQryAux := " SELECT "                                                                        + CRLF
		cQryAux += " 	ISNULL(MAX(B1_COD), '" + cCodigo + "') AS ULTIMO "                           + CRLF
		cQryAux += " FROM "                                                                          + CRLF
		cQryAux += " 	" + RetSQLName('SB1') + " SB1 "                                              + CRLF
		cQryAux += " WHERE "                                                                         + CRLF
		cQryAux += " 	B1_FILIAL = '" + FWxFilial('SB1') + "' "                                     + CRLF
		cQryAux += " 	AND B1_GRUPO = '" + cGrupo + "' "                                            + CRLF
		cQryAux += " 	AND SUBSTRING(B1_COD, 1, " + cValToChar(nTamGrp) + ") = '" + cGrupo + "' "   + CRLF
		TCQuery cQryAux New Alias "QRY_AUX"
		
		//Define o novo código, incrementando 1 no final
		cCodigo := Soma1(cCodigo)
		
		QRY_AUX->(DbCloseArea())
	EndIf
	
	RestArea(aArea)
Return cCodigo

Ressalto que outras tratativas como 2 usuários incluírem ao mesmo tempo, ou tratativas específicas, esse fonte não abrange, ele é apenas um facilitador para inclusão desse recurso.

Bom pessoal, por hoje é só.
Abraços e até a próxima.

Dan Atilio (Daniel Atilio)
Especialista em Engenharia de Software pela FIB. Entusiasta de soluções Open Source. E blogueiro nas horas vagas.

16 Responses

  1. Julio Cesar Correr disse:

    Boa tarde Comigo não funcionou se eu incluir um novo item o mesmo grupo ele informa que o item já possui cadastro pelo que entendi o sistema não esta somando + 1

  2. Julio Correr disse:

    Boa tarde Dan_Atilio ,

    Consegui fazer seu processo e me atendeu bem porém se eu tentar cadastrar um novo item com o mesmo grupo o protheus informa que a chave esta duplicada , então todo momento de trocar o grupo

    • Dan_Atilio disse:

      Bom dia.
      Vamos por partes, você quer alterar o grupo de um produto já existente?
      Se sim, talvez essa função não seja a melhor, já que o grupo seria um tipo de “chave”.
      Agora se for não, teria que testar a query e debugar para ver seu conteúdo.

  3. Julio Cesar disse:

    Bom dia Dan , primeiramente muito obrigado pelo retorno vou tentar explicar melhor então digamos que eu tenha um grupo que tem o codigo TRA meu item é para ser TRA000000001 ok.
    Isso o sistema faz agora se cadastrarmos um novo item usando o grupo TRA (que ficaria TRA000000002) o sistema não faz da erro informa que o item já esta cadastrado.

    Debuguei a query pelo TDS e no final da execução ela traz TRA0000000000 ai ele faz função soma1 fica TRA00000000001
    por isso o erro.

    • Dan_Atilio disse:

      Boa tarde Julio.
      E no caso, da sua query, se você executa ela no banco, ela retorna o que? o TRA0000000? Se sim, pode ser algum erro na própria query, pois era pra ela pegar o último registro.
      Uma dúvida, seu campo de grupo, tem 4 dígitos? Pois “TRA” só tem 3, então você tem que tratar na query isso, diminuindo o tamanho da variável nTamGrp.

  4. Maramaldo disse:

    O programa realmente estava se comportando como os colegas informaram nos comentário. Não estava sendo incrementado após a inclusão do segundo produto de um determinado grupo. Fiz uma alteração no fonte, agora acho que está ok.

    //Bibliotecas
    #Include “Protheus.ch”
    #Include “TopConn.ch”

    /*/{Protheus.doc} zGrupCod
    Função que preenche o código do produto conforme o grupo
    @author Atilio
    @since 04/04/2018
    @version 1.0
    @type function
    @obs Passo a Passo de como fazer para funcionar:
    1. Acesse o Configurador (SIGACFG), vá na tabela SB1 e clique em Editar
    2. Vá no campo Grupo (B1_GRUPO), verifique se ele está como obrigatório, caso não esteja, deixe ele como obrigatório (está na aba Uso)
    3. No modo de edição do campo, deixe a expressão INCLUI para ele ficar habilitado apenas na inclusão (está na aba Opções)
    4. Altere a sequência do campo, para ele vir antes do campo Código (B1_COD)
    5. Vá no campo Código (B1_COD), no modo de edição deixe a expressão .F. para não deixar alterar o campo
    6. Confirme as alterações da tabela
    7. Vá na seção de Gatilhos, e clique para incluir um novo Gatilho. Nesse Gatilho, coloque a origem sendo o B1_GRUPO, e o destino o B1_COD, e a Regra sendo u_zGrupCod()
    8. Salve as alterações do Configurador
    9. Compile a função abaixo
    /*/

    User Function zGrupCod()
    Local aArea := GetArea()
    Local cCodigo := “”
    Local cGrupo := FWFldGet(“B1_GRUPO”)
    Local cQryAux := “”
    Local nTamGrp := TamSX3(‘B1_GRUPO’)[01]
    Local nTamCod := TamSX3(‘B1_COD’)[01]

    //Se houver grupo
    If ! Empty(cGrupo)
    cCodigo := cGrupo + Replicate(‘0’, nTamCod-nTamGrp)

    //Pegando o último código (não foi fitraldo o DELET para manter a sequencia unica)
    cQryAux := ” SELECT ” + CRLF
    cQryAux += ” ISNULL(MAX(B1_COD), ‘” + cCodigo + “‘) AS ULTIMO ” + CRLF
    cQryAux += ” FROM ” + CRLF
    cQryAux += ” ” + RetSQLName(‘SB1’) + ” SB1 ” + CRLF
    cQryAux += ” WHERE ” + CRLF
    cQryAux += ” B1_FILIAL = ‘” + FWxFilial(‘SB1’) + “‘ ” + CRLF
    cQryAux += ” AND B1_GRUPO = ‘” + cGrupo + “‘ ” + CRLF
    cQryAux += ” AND SUBSTRING(B1_COD, 1, ” + cValToChar(nTamGrp) + “) = ‘” + cGrupo + “‘ ” + CRLF
    TCQuery cQryAux New Alias “QRY_AUX”

    //FONTE GIANNINY MARAMALDO
    dbSelectArea(“QRY_AUX”)

    While !QRY_AUX->(EOF())
    cCodigo := QRY_AUX->ULTIMO
    QRY_AUX->(dbSkip())
    EndDo

    //Define o novo código, incrementando 1 no final
    cCodigo := Soma1(cCodigo)

    Alert(cCodigo)

    QRY_AUX->(DbCloseArea())
    //FIM DE FONTE GIANNINY MARAMALDO
    EndIf

    RestArea(aArea)
    Return cCodigo

  5. Diego disse:

    Bom dia estamos tentado fazer esta configuração porém não estamos conseguindo pois utilizamos Protheus em T-Cloud.
    Alguém poderia nos auxiliar?

  6. Diego Andrade disse:

    fiz exatamente o que informou o texto acima mas a minha dúvida é onde compilo a função?
    É no CFG?

  7. Diego disse:

    Fizemos todo o passo a passo mas travamos na mensagem abaixo:

    Inconsistência
    Erro no Gatilho:B1_GRUPO Sec.001
    InterFunctionCall: cannot find function U_ZGRUPCOD in AppMap
    Nos de uma luz comoresolver;

    Lembrando que utilizamos o Protheus T-Cloud;

    • Dan_Atilio disse:

      Então Diego, você deve configurar uma base de desenvolvimento do TCloud no VSCode, a partir disso, siga os procedimentos:
      1 – Compilar o código fonte no VSCode nesse ambiente de testes, com Ctrl+F9
      2 – Aperte Ctrl+Shift+P, e vá na opção totvs gerar patch, ou generation patch file, digite o nome desse prw, e gere a patch .ptm em alguma pasta
      3 – No TCloud, vá em aplicar patch, e aponte para essa patch gerada no passo número 2

Deixe uma resposta