#05 – WorkFlow de Aprovação de Solicitação de Compras

#05 – WorkFlow de Aprovação de Solicitação de Compras

Hoje no quinto post da série de WorkFlow de Aprovação de Solicitação de Compras, iremos demonstrar como criar as funções de envio do e-mail, e recebimento da reposta do processo de WorkFlow.

A nossa customização é dividia basicamente em 04 (quatro) funções, que são elas:

  • User Function SSCOM002 – Função principal que será chamada pelo PE M110STTS (demonstrado no terceiro post da série);
  • Static Function SSCOM002WK – Função responsável por “montar” os arquivos HTML de envio do Link e do formulário de Aprovação do WorkFlow;
  • User Function SCRetorno – Função responsável por receber a Aprovação/Rejeição do processo de WorkFlow, atualizar as devidas informações na Solicitação de Compra (SC) do Protheus, e disparar a função de envio de notificação do processo;
  • User Function SCNotificar – Função responsável por notificar a tomada de decisão do processo de WorkFlow. No nosso caso, ou a SC é Aprovada ou Rejeitada.

Não iremos nesse post explicar detalhadamente cada passo das funções, pois o post ficaria e enorme e cansativo, além do que, as funções estão documentadas linha a linha.

Em termos gerais, o que a nossa customização faz, é obter os dados da SC do Protheus, gerar o link e formulário de aprovação, com os dados da SC, após essa SC ser Aprovada ou Rejeitada, receber tal informações e atualizar os dados no Protheus.

Temos ainda também nas funções, a utilização de métodos para que seja possível rastrear os passos do WorkFlow, através do comando Track.

Segue o fonte completo da customização do WorkFlow de Aprovação de Solicitação de Compras:

#Include 'Protheus.ch'
#Include "Rwmake.ch"

User Function SSCOM002()

  Local aArea		:= GetArea()

  Private cNomeSup	:= "Smart Siga Aprovador"

  MsgRun("Gerando WorkFlow de Aprovacao, Aguarde...","",{|| CursorWait(), SSCOM002WK(), CursorArrow()})

  //Retorna o Posicionamento Original do Arquivo
  RestArea(aArea)

Return

//******************************
Static Function SSCOM002WK()

  Local oProcess 	:= Nil 
  Local oHtml		:= Nil
  Local cDestinatario	:= ""
  Local cShape		:= ""
  Local cArqHtml	:= ""
  Local cAssunto	:= ""
  Local cUsrCorrente	:= ""
  Local cCodigoStatus	:= ""
  Local cHtmlModelo	:= ""
  Local cNumSC		:= ca110Num
  Local cDescricao	:= ""
  Local cUser     	:= __cUserID
  Local cMailID		:= "" 

  //Assunto do E-mail
  cAssunto := "Aprovacao da S.C.  No: " + cNumSC

  //Caminho e Arquivo HTML do Link de Formulario de Aprovacao
  cArqHtml := "\Workflow\WFSCEnvio.html"

  //Obtem o Usuario Logado
  cUsrCorrente := SubStr(cUsuario, 7, 15)

  //Destinatario Separado por Ponto e Virgulha(;)
  cDestinatario := "emailaprovacao@dominio.com.br"

  //Inicia o Processo de WorkFlow de Aprovacao de SC
  oProcess := TWFProcess():New( "SCCOM", cAssunto )

  //Cria uma Nova Tarefa Informando o HTML do Link de Envio
  oProcess:NewTask( "Aprovacao da S.C.", cArqHtml )

  //Informa o Codigo e Descricao do Status do Processo Correspondente ao Inicio do Start de WorkFlow 
  cCodigoStatus 	:= "100100"
  cDescricao 	:= "Inicio do Processo de Aprovacao da SC"

  //Ratreabilidade com o Codigo do Status, Descricao e Usuario Logado 
  oProcess:Track( cCodigoStatus, cDescricao, cUsrCorrente)

  //Função de Retorno da Aprovacao do WorkFlow de SC
  oProcess:bReturn  := "U_SCRetorno"
  oProcess:cSubject := cAssunto


  //Usuario Responsavel pelo Processo do WorkFlow de Aprovacao de SC
  oProcess:UserSiga := WFCodUser( cUser )

  //Cria Objeto HTML do Processo de WorkFlow de Aprovacao de SC
  oHtml := oProcess:oHTML

  //Informa o Codigo e Descricao do Status do Processo Correspondente ao Inicio do Start de WorkFlow 
  cCodigoStatus 	:= "100200"
  cDescricao 	:= "Gerando Processo de Aprovacao da SC"	

  //Ratreabilidade com o Codigo do Status, Descricao e Usuario Logado
  oProcess:Track(cCodigoStatus, cDescricao, cUsrCorrente )

  // Preenche os Campos do HTML com as Informacoes da SC
  oHtml:ValByName( "Dt_Emissao" , DtoC(SC1->C1_EMISSAO))
  oHtml:ValByName( "Dt_Entrega" , DtoC(SC1->C1_DATPRF))
  oHtml:ValByName( "Solicitante", SC1->C1_SOLICIT)
  oHtml:ValByName( "CC"         , SC1->C1_CC + " - " + SC1->C1_ITEMCTA)
  oHtml:ValByName( "Aprovacao"  , "Bloqueada")
  oHtml:ValByName( "Aprovador"  , cNomeSup)
  oHtml:ValByName( "Num_SC"	, cNumSC )

  DBSelectArea("SC1")
  SC1->(DBSetOrder(1))
  SC1->(DBSeek(FwFilial("SC1") + cNumSC))

  // Preencha o Arquivo HTML com as Informacoes da SC
  While !SC1->( EOF() ) .And. (SC1->C1_FILIAL == FwFilial("SC1") .And. SC1->C1_NUM == cNumSC)		

    AADD( ( oHtml:ValByName( "TB.Item"   ))	, SC1->C1_ITEM    )
    AADD( ( oHtml:ValByName( "TB.Codigo" ))	, SC1->C1_PRODUTO )
    AADD( ( oHtml:ValByName( "TB.Descricao" ))	, SC1->C1_DESCRI + " " + SC1->C1_OBS )
    AADD( ( oHtml:ValByName( "TB.Qtd" ))	, Transform( SC1->C1_QUANT,'@E 999,999.99' ) )
    AADD( ( oHtml:ValByName( "TB.Unid" ))       , SC1->C1_UM  )

    //Criar a Cor das Linhas em Zebrado atraves da verificacao se a Linha é Par ou Impar
    If (Val(SC1->C1_ITEM)%2) = 0
      AADD(oHTML:ValByName('TB.Fundo'),"#FFFFFF")
    Else
      AADD(oHTML:ValByName('TB.Fundo'),"#f3f3f3")

    EndIf

    SC1->(DbSkip())

  Enddo

  //Salva o Processo de WorkFlow na Pasta SSCOM002
  oProcess:cTo := "SSCOM002"

  //Cria o Processo de WorkFlow para Aprovacao de SC
  cMailID := oProcess:Start()

  //Associa o Arquivo HTML do Link
  cHtmlModelo := "\workflow\WFSCLink.html"

  //Cria uma Nova Tarefa par ao Processo de Aprovacao de WorkFlow de SC
  oProcess:NewTask(cAssunto, cHtmlModelo)

  //E-mail do Aprovador do Processo de Aprovacao de WorkFlow de SC
  oProcess:cTo := "emailaprovacao@dominio.com.br" 

  //Substitui as Macros do Arquivo HTML do Link
  oProcess:oHTML:ValByName("usuario"  , AllTrim(cNomeSup))
  oProcess:oHTML:ValByName("referente", cNumSC)	
  oProcess:oHTML:ValByName("proc_link", "http://localhost:1236/WorkFlow/Messenger/Emp99/SSCOM002/" + cMailID + ".htm")

  //Informa o Codigo e Descricao do Status do Processo Correspondente ao Inicio do Start de WorkFlow
  cCodigoStatus 	:= "100300"
  cDescricao 	:= "Enviando Processo de Aprovação da SC"

  //Ratreabilidade com o Codigo do Status, Descricao e Usuario Logado
  oProcess:Track( cCodigoStatus, cDescricao, cUsrCorrente )

  //Inicia o Processo de Envio de E-mail do WorkFlow de Aprovacao de SC
  oProcess:Start()

Return Nil

//Funcao de Retorno da Aprovacao/Rejeicao do WorkFlow
User Function SCRetorno(oProcess)

  //Variaveis Locais
  Local cAssunto	:= ""
  Local cNumSC		:= ""
  Local cCodigoStatus	:= ""
  Local cDescricao	:= ""
  Local cDescWork	:= ""
  Local cCor		:= ""
  Local cAprovador	:= ""
  Local cAprovacao	:= ""
  Local cStatusAP	:= ""
  Local cMotRejec	:= ""


  //Recupera o Numero da SC do Processo de WorkFlow
  cNumSC := oProcess:oHtml:RetByName("Num_SC")

  //Informa o Codigo e Descricao do Status do Processo Correspondente ao Inicio do Start de WorkFlow 
  cAssunto 	:= "Solicitacao de Compras no: " + cNumSC
  cCodigoStatus	:= "100400"
  cDescricao 	:= "Aguardando Aprovacao da SC"

  //Ratreabilidade com o Codigo do Status, Descricao e Usuario Logado 
  oProcess:Track( cCodigoStatus, cDescricao )

  //Verifica se o WorkFlow de Processo de Aprovacao de SC foi Aprovador ou Rejeitado
  If Upper(oProcess:oHtml:RetByName("RBAPROVA")) <> "SIM"

    //Varives de Controle de Aprovacao de WorkFlow de Aprovacao de SC
    cAprovacao	:= "Rejeitada"
    cStatusAP	:= "R"
    cMotRejec	:= oProcess:oHtml:RetByName('lbmotivo')
    
    ConOut("Teste Rejeicao: " + cMotRejec)

    //Cria uma Nova Tarefa par ao Processo de Aprovacao de WorkFlow de SC
    cCodigoStatus 	:= "100600"
    cDescricao 	:= "SC Reprovada"
    cCor 		:= "#FF6600"		

  Else

    //Varives de Controle de Aprovacao e Motivo de Rejeicao do WorkFlow de Aprovacao de SC
    cAprovacao 	:= "Aprovada"
    cStatusAP	:= "L"		
    
    //Cria uma Nova Tarefa par ao Processo de Aprovacao de WorkFlow de SC
    cCodigoStatus := "100500"
    cDescricao 	  := "SC Aprovada"
    cCor 	  := "#009900"	

  EndIf

  DBSelectarea("SC1")
  DBSetOrder(1)
  SC1->(dbSeek(FwFilial("SC1") + cNumSC))

  While !SC1->(EOF()) .And. ( SC1->C1_FILIAL == FwFilial("SC1") .And. SC1->C1_NUM == cNumSC)

    RecLock("SC1",.F.)

    SC1->C1_APROV 	:= cStatusAP
    SC1->C1_NOMAPRO	:= oProcess:oHtml:RetByName("Aprovador")
    SC1->C1_OBS	        := AllTrim(SC1->C1_OBS) + IIF(AllTrim(SC1->C1_OBS) == "" .Or. AllTrim(cMotRejec) == "", "", " - ") + cMotRejec

    SC1->(MsUnLock())

    SC1->(DBSkip())

  EndDo
  
  //Associa a Descricao do Track ao Titulo da Notificacao
  cDescWork := cDescricao 

  //Ratreabilidade com o Codigo do Status, Descricao e Usuario Logado 
  oProcess:Track( cCodigoStatus, cDescricao )

  // Execute a função responsável pela notificação ao usuário solicitante.
  U_SCNotificar( oProcess, cDescWork, cCor, cAprovacao )

Return Nil

//Funcao de Notificacao do WorkFlow de Aprovacao de SC
User Function SCNotificar( oProcess, cDescWork, cCor, cAprovacao )

  Local oHtml		:= Nil
  Local aValues 	:= Array(17)
  Local cCodigoStatus	:= ""
  Local cDescricao	:= ""
  Local cArqHtml	:= ""
  
  //Caminho e Arquivo HTML do Link de Formulario de Aprovacao
  cArqHtml := "\Workflow\WFSCAprov.html"

  //Informa o Codigo do Status do Processo Correspondente ao Inicio do Start de WorkFlow
  cCodigoStatus	:= "100700"
  cDescricao 	:= "Notifica a Aprovacao/Reprovacao ao Solicitante e ao Departamento de Compras"

  //Ratreabilidade com o Codigo do Status, Descricao e Usuario Logado
  oProcess:Track( cCodigoStatus, cDescricao )

  //Cria Objeto HTML do Processo de WorkFlow de Aprovacao de SC
  oHtml := oProcess:oHtml

  //Atribui os Valores Recuperados do HTML ao Array aValues
  aValues[01] := oHtml:ValByName("Num_SC")
  aValues[02] := oHtml:ValByName("Dt_Emissao")
  aValues[03] := oHtml:ValByName("Dt_Entrega")
  aValues[04] := oHtml:ValByName("Solicitante")
  aValues[05] := oHtml:ValByName("CC")
  aValues[06] := oHtml:ValByName("TB.Item")
  aValues[07] := oHtml:ValByName("TB.Codigo")
  aValues[08] := oHtml:ValByName("TB.Unid")
  aValues[09] := oHtml:ValByName("TB.Descricao")
  aValues[10] := oHtml:ValByName("TB.Qtd")
  aValues[11] := oHtml:ValByName("TB.Fundo")
  aValues[12] := oHtml:ValByName("Aprovador")
  aValues[13] := oHtml:ValByName("Projeto")
  aValues[14] := oHtml:ValByName("Objetivo")

  //Cria uma Nova Tarefa Informando o HTML do Link de Envio
  oProcess:NewTask("Resultado da Aprovação", cArqHtml )

  //oHtml := oProcess:oHtml

  //Recupera as Informacoes do Array e Preenche o Arquivo HTML de Notificao
  oHtml:ValByName("Num_SC"	, aValues[01] )
  oHtml:ValByName("Dt_Emissao"	, aValues[02] )
  oHtml:ValByName("Dt_Entrega"	, aValues[03] )
  oHtml:ValByName("Solicitante"	, aValues[04] )
  oHtml:ValByName("CC"		, aValues[05] )
  oHtml:ValByName("Aprovador"	, aValues[12] )
  oHtml:ValByName("Projeto"	, aValues[13] )
  oHtml:ValByName("Objetivo" 	, aValues[14] )

  //Recupera as Informacoes do Array e Preenche o Arquivo HTML de Notificao
  AEval( aValues[06],{ |x| AADD( oHtml:ValByName( "TB.Item" )	  , x ) } )
  AEval( aValues[07],{ |x| AADD( oHtml:ValByName( "TB.Codigo" )	  , x ) } )
  AEval( aValues[08],{ |x| AADD( oHtml:ValByName( "TB.Unid" )	  , x ) } )
  AEval( aValues[09],{ |x| AADD( oHtml:ValByName( "TB.Descricao" ), x ) } )
  AEval( aValues[10],{ |x| AADD( oHtml:ValByName( "TB.Qtd" )	  , x ) } )
  AEval( aValues[11],{ |x| AADD( oHtml:ValByName( "TB.Fundo" ) 	  , x ) } )

  ////Recupera as Informacoes das Variaveis e Preenche o Arquivo HTML de Notificao
  oHtml:ValByName( "Titulo"    , cDescWork )
  oHtml:ValByName( "Cor_Tit"   , cCor )
  oHtml:ValByName( "Cor_Itens" , cCor )
  oHtml:ValByName( "Aprovacao" , cAprovacao)
  oHtml:ValByName( "Dt_Aprov"  , dDataBase )
  oHtml:ValByName( "Hora_Aprov"	, Time()  )

  //E-mail que Ira Receber a Notificacao de Aprovacao/Rejeicao do Processo de WorkFlow
  oProcess:cTo      := "emailaprovacao@dominio.com.br"

  //Assunto do E-mail que Ira Receber a Notificacao de Aprovacao/Rejeicao do Processo de WorkFlow
  oProcess:cSubject := "Retorno da Aprovacao da Solicitacao de Compras"

  //Cria e Inicia o Processo de Envio de E-mail do WorkFlow de Aprovacao de SC
  oProcess:Start()

  //Informa o Codigo e Descricao do Status do Processo Correspondente ao Inicio do Start de WorkFlow 
  cCodigoStatus := "100800"
  cDescricao := "Finalizacao do Processo de Workflow de Aprovacao de SC"

  //Ratreabilidade com o Codigo do Status, Descricao e Usuario Logado
  oProcess:Track( cCodigoStatus, cDescricao )

Return Nil
Fonte 01 – Envio e Recebimento do WorkFlow de Aprovação de Solicitação de Compras

No vídeo abaixo, demonstramos o funcionamento completo do processo WorkFlow de Aprovação de Solicitação de Compras no Protheus:

Vídeo 01 – Demonstração completa do processo de WorkFlow de Aprovação de Solicitação de Compras

Como podemos verificar no vídeo, ao receber o e-mail, e clicar no link de Aprovação, o formulário HTML é aberto diretamente no Browser via Servidor Web do Protheus. Ao selecionar a opção de Aprovar ou Rejeitar, a resposta é enviada diretamente ao Protheus, a qual executa a função de retorno SCRetorno, atualizando o status da SC, além de salvar dados como nome do aprovador e observação.

A cutomização ainda envia ao solicitante através da função SCNotificar, o e-mail de notificação na cor da legenda da SC, isto é, se a SC foi aprovada, as cores da notificação serão em verde, se for rejeitada, as cores de notificação serão em laranja.

A alteração de cor dos e-mails de notificação, é toda realizada na customização de envio e recebimento da aprovação ou rejeição do WorkFlow de Aprovação de Solicitação de Compras.

Para baixar o fonte de envio e recebimento do WorkFlow diretamente do nosso GitHub, clique aqui.

Com isso finalizamos nosso penúltimo post da série de WorkFlow de Aprovação de Solicitação de Compras.

No próximo e último post, iremos demonstrar como realizar o rastreamento do WorkFlow.

Caso queiram verificar todos os posts relacionados a WorkFlow no Protheus, basta clicar aqui.

Caso ainda não tenham se inscrito no Canal Smart Siga, ou em nossas mídias sociais, ou em nosso GitHub, aproveitem para se cadastrar agora, pois assim, vocês recebem em primeira mão, todas as novidades do nosso site.

Aproveitem também, para ingressar em nosso Canal do Smart Siga no Telegram. Para tanto acessem: https://t.me/smartsiga.

Smart Siga - TI Inteligente

Icons made by Prosymbols from www.flaticon.com is licensed by CC 3.0 BY
Compartilhe:
  •  
  •  
  •  

12 thoughts on “#05 – WorkFlow de Aprovação de Solicitação de Compras

  1. Showwwwwwww parabéns, até que enfim um passo a passo de Workflow que realmente funciona, e ainda com o fonte disponível.
    Que tal postar isso no TDN kssss vai ajudar muito.

    1. Bom dia Douglas,

      Muito obrigado pelo seu comentário.

      Continue nos acompanhando.

      Abs,

      Cristian Regazzo
      Smart Siga
      TI Inteligente

  2. Está de parabéns amigo … Esta ajudando e muito .. seu site esta otimo, perfeito .. So tenho q agradecer … muito obrigado ! 🙂

    1. Boa Tarde Vitor,

      Obrigado pelo seu comentário e obrigado por nos acompanhar!!!

      Que bom que o Smart Siga está lhe ajudando. Ficamos muito felizes com essa informação.

      Abs,

      Cristian Regazzo
      Smart Siga
      TI Inteligente

  3. Por acaso, devido a necessidade, acabei encontrando o seu site e esse passo a passo sobre o workflow. Realmente muito bom. Agradeço por isso. Porem eu ainda estou tendo problema seguindo a sua configuração no appserver.ini em fazer o html a ser aberto pelo link, funcionar(o email é enviado, mas ao clicar no “link” não consigo abrir o html no browser), Estou rodando tudo dentro do mesmo servidor, inclusive abrindo meu email em um browser dentro do servidor. Vi que o hmtl é criado na pasta correta dentro do subdiretorio messenger, mas o html mesmo não abre no browser. Se puder ajudar agradeço.

    1. Boa Tarde Mauricio,

      Obrigado pelo seu comentário e obrigado por nos acompanhar.

      Verifique se a sua seção HTTP, esta da seguinte forma no AppServer:

      [HTTP]
      RPCEnv=P12
      enable=1
      path=C:\Totvs\TOTVS12\Microsiga\Protheus\Protheus_Data
      port=1236

      Verifique também, se o parâmetro MV_WFWEBEX está com .F.

      Abs,

      Smart Siga
      TI Inteligente

  4. Boa tarde, muito bom seu trabalho, poderia me tirar uma duvida, não está abrindo no navegador o html gerado, na verdade dentro da pasta do workflow não gera nada. Alguma dica do que pode ser? Obrigado!

    1. Bom dia Luiz,

      Muito obrigado pelo por nos acompanhar e pelo seu comentário.

      Verifique no Console do AppServer, se está sendo gerado algum erro.

      A configuração HTTP do AppServer.ini está correta?

      A pasta WorkFlow, existe dentro da Protheus_Data?

      Abs,

      Smart Siga
      TI Inteligente

  5. Cristian, tudo bem? ficou ótimo o seu trabalho. Eu gostaria de saber se conseguimos pegar direto do sistema o e-mail dos aprovadores ou se será necessário adicionar no fonte o e-mail, sempre que houver uma alteração nos aprovadores cadastrados.

    Aguardo seu retorno e, parabéns!

    1. Boa Tarde Sra. Thayná,

      Obrigado pelo seu comentário e obrigado por nos acompanhar.

      Da forma que está o exemplo hoje nos posts, você terá que adicionar o email do aprovador diretamente no fonte.

      Mas nada impende de fazer um ajuste no fonte, e “pegar” esses e-mails diretamente do cadastro de usuários, ou de repente, fazer uma tabela customizada com os aprovadores e seus respectivos e-mails.

      Att,

      Smart Siga
      TI Inteligente

  6. Boa tarde, no envio de e-mail criei uma tabela customizada para enviar os emails, porem na notificação não reconhece a tabela, alguém pode dar uma dica de como resolver isso??

    1. Bom dia Lucas, tudo bem?

      Obrigado pelo seu comentário e obrigado por nos acompanhar.

      Poderia especificar melhor o problema?

      Qual notificação você está se referindo?

      Obrigado.

      Att,

      Smart Siga
      TI Inteligente

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Seja um Analista VIP!!!

Recebe em primeira mão as novidades do Canal Smart Siga, além de conteúdos exclusivos.