Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

...

Exemplos: Salvar os arquivos html com o título descrito no exemplo nfcwfcustom1.html e nfcwfcustom2.html




Aviso

Ao ativar este ponto de entrada, o workflow padrão será integralmente substituído pelo workflow customizado. As telas de envio de e-mail serão simplificadas, exibindo apenas o campo para informar os endereços de e-mail e o botão de envio do workflow.





Bloco de código
languagedelphi
themeMidnight
titleExemplo NFCWFCUSTOM.prw
linenumberstrue
#include "PROTHEUS.CH"
#include "FWMVCDEF.CH"
 
User Function NFCWFCUSTOM()
    Local aAreas := {DHU->(GetArea()), SC8->(GetArea()), GetArea()}
    Local oJsonWF := Paramixb[1]
    Local oJsonResp := JsonObject():New()
    Local oProcess := Nil
    Local cNumCot := ''
    Local nCode := 200
    Local cMessage := ''
    Local lOk := .T.
    Local nX := 0
    Local aSuppliers := {}
    Local cFilialSC8 := FWxFilial('SC8')
    Local cForn := ''
    Local cLoja := ''
    Local cForNome := ''
    Local cEmail := ''
    Local cLastProp := ''
    Local cNomeWF := 'nfcwfcustom'
    Local cMailBox := ''
    Local cDirWF := AllTrim( WFGetMV( "MV_WFDIR", "" ) )
	Local cSrLkWF := AllTrim( WFGetMV( "MV_WFBRWSR", "127.0.0.1:80" ) )
    Local cHtmlMail1 := 'nfcwfcustom1.html' //-- Nome do arquivo HTML que será utilizado no envio do workflow
    Local cHtmlMail2 := 'nfcwfcustom2.html' //-- Nome do arquivo HTML que será utilizado como corpo do e-mail
    Local cProductDesc := ''
    Local cIDWF := ''
    Local cIDLink := ''
    Local aTQuant := TamSX3("C8_QUANT")
    Local aTQtDisp := TamSX3("C8_QTDISP")
    Local aTPreco := TamSX3("C8_PRECO")
    Local aTTotal := TamSX3("C8_TOTAL")
    Local cUserLog := RetCodUsr()
    Local nLenNum := TamSX3('C8_NUM')[1]
    Local nLenForn := TamSX3('C8_FORNECE')[1]
    Local nLenLoja := TamSX3('C8_LOJA')[1]
    Local nLenForNome := TamSX3('C8_FORNOME')[1]

    //-- Exemplo de estrutura do JSON contido em oJsonWF
    /*
    
        {
            "quotation": "000230", // Número da cotação
            "suppliers": [ //-- Array de fornecedores que receberão o workflow
                {
                    "supplier": "000001", // Código do fornecedor
                    "store": "01", // Código da loja
                    "corporatename": "HOSPITAL MATER DEI", // Nome do fornecedor
                    "email": "[email protected]" // E-mail do fornecedor (pode conter mais de um e-mail separado por ponto e vírgula ex: "[email protected];[email protected]")
                }
            ]
        }

    */

    //-- Cabeçalho da cotação
    DHU->(DbSetOrder(1)) //-- DHU_FILIAL+DHU_NUM

    cNumCot := padR(oJsonWF['quotation'], nLenNum)

    If lOk := DHU->(DbSeek(FWxFilial('DHU') + cNumCot))
        cMessage := "Processo de workflow enviado com sucesso."

        //Exemplo de obtenção dos e-mails dos fornecedores para envio do workflow
        aSuppliers := oJsonWF['suppliers']

        For nX := 1 To Len(aSuppliers)
            cForn := padR(aSuppliers[nX]['supplier'], nLenForn) //SC8->C8_FORNECE
            cLoja := padR(aSuppliers[nX]['store'], nLenLoja)    //SC8->C8_LOJA
            cForNome := padR(aSuppliers[nX]['corporatename'], nLenForNome) //SC8->C8_FORNOME
            cEmail := AllTrim(aSuppliers[nX]['email']) //Email preenchido no envio do workflow
            cLastProp := PGCLastProp(cNumCot,cForn,cLoja,cForNome) //Função que retorna a última proposta do fornecedor (C8_NUMPRO)

            // Aqui você pode implementar a lógica de envio do e-mail para o fornecedor
            // Utilizando as variáveis cForn, cLoja, cForNome, cEmail e cLastProp

            SC8->(DbSetOrder(8))
            If !SC8->(DbSeek(cFilialSC8+cNumCot+cForn+cLoja+cForNome)) // Posiciona na Cotação do Fornecedor
                cMessage := 'A proposta do fornecedor ' + AllTrim(cForNome) + ' não foi localizada na base de dados.'
                lOk := .F.
                Exit
            EndIf

            //-- Posiciona na proposta atual do fornecedor
            While SC8->(!Eof()) .And. (cFilialSC8+cNumCot+cForn+cLoja+cLastProp+cForNome) <> SC8->(C8_FILIAL+C8_NUM+C8_FORNECE+C8_LOJA+C8_NUMPRO+C8_FORNOME)
                SC8->(DbSkip())
            EndDo
            
            oProcess := TWFProcess():New(cNomeWF, DecodeUTF8(EncodeUTF8('Envio de Workflow para Cotação'))) // 'Envio de Workflow para Cotação'

            If lOk := WF7->(MsSeek(FWxFilial('WF7')))
                cMailBox := WF7->WF7_PASTA //-- Pode ser obtido na tabela WF7
            Else
                cMessage := 'Caixa de e-mail não cadastrada.'
                Exit
            EndIf

            oProcess:oWf:cMailBox := cMailBox
            oProcess:cFrom        := cMailBox

            oProcess:NewTask(cNomeWF, cDirWF + "\" + cHtmlMail1)
            oProcess:cSubject := DecodeUTF8(EncodeUTF8('Solicitação de Cotação')) // 'Solicitação de Cotação'
            oProcess:bReturn  := 'u_WfCustom()' //-- Função de retorno quando o fornecedor responder o workflow
            oProcess:bTimeOut := {{"__WFTimeout()", 0, 0, 5 }}

            oProcess:oHTML:ValByName('cFilCot' , FWxFilial('DHU'))
            oProcess:oHTML:ValByName('cNumCot' , SC8->C8_NUM)
            oProcess:oHTML:ValByName('cFornece', SC8->C8_FORNECE)
            oProcess:oHTML:ValByName('cLoja'   , SC8->C8_LOJA)
            oProcess:oHTML:ValByName('cForNome', cForNome)
            oProcess:oHTML:ValByName('cNumProp', SC8->C8_NUMPRO)
            oProcess:oHTML:ValByName('DHU_COND', SC8->C8_COND) //Condição de pagamento

            //Strings do template HTML nfcwfcustom1.html
            oProcess:oHTML:ValByName("cSTR1" , DecodeUTF8(EncodeUTF8("Solicitação de Cotação")))
            oProcess:oHTML:ValByName("cSTR2" , DecodeUTF8(EncodeUTF8("Solicitação de Cotação - Nº")))
            oProcess:oHTML:ValByName("cSTR3" , DecodeUTF8(EncodeUTF8("- Proposta")))
            oProcess:oHTML:ValByName("cSTR4" , DecodeUTF8(EncodeUTF8("Fornecedor")))
            oProcess:oHTML:ValByName("cSTR5" , DecodeUTF8(EncodeUTF8("Código / Loja")))
            oProcess:oHTML:ValByName("cSTR6" , DecodeUTF8(EncodeUTF8("Filial Cotação")))
            oProcess:oHTML:ValByName("cSTR7" , DecodeUTF8(EncodeUTF8("Itens da Cotação")))
            oProcess:oHTML:ValByName("cSTR8" , DecodeUTF8(EncodeUTF8("Item")))
            oProcess:oHTML:ValByName("cSTR9" , DecodeUTF8(EncodeUTF8("Produto")))
            oProcess:oHTML:ValByName("cSTR10", DecodeUTF8(EncodeUTF8("Descrição")))
            oProcess:oHTML:ValByName("cSTR11", DecodeUTF8(EncodeUTF8("Qtde")))
            oProcess:oHTML:ValByName("cSTR12", DecodeUTF8(EncodeUTF8("Qtde Disp.")))
            oProcess:oHTML:ValByName("cSTR13", DecodeUTF8(EncodeUTF8("Preço Unit.")))
            oProcess:oHTML:ValByName("cSTR14", DecodeUTF8(EncodeUTF8("Total")))
            oProcess:oHTML:ValByName("cSTR15", DecodeUTF8(EncodeUTF8("Observação")))
            oProcess:oHTML:ValByName("cSTR16", DecodeUTF8(EncodeUTF8("Enviar")))
            oProcess:oHTML:ValByName("cSTR17", DecodeUTF8(EncodeUTF8("Condição de pagamento")))
            
            //-- Carrega itens da cotação referente a última proposta do fornecedor
            While SC8->(!Eof()) .And. (cFilialSC8+cNumCot+cForn+cLoja+cForNome) == SC8->(C8_FILIAL+C8_NUM+C8_FORNECE+C8_LOJA+C8_FORNOME)
                If cLastProp == SC8->C8_NUMPRO //-- Apenas a última proposta
                    Aadd(oProcess:oHTML:ValByName('It.C8_PRODUTO'), SC8->C8_PRODUTO)
                    Aadd(oProcess:oHTML:ValByName('It.C8_ITEM'), SC8->C8_ITEM)

                    cProductDesc := GetAdvFval("SB1","B1_DESC", FWxFilial('SB1') + SC8->C8_PRODUTO, 1)

                    Aadd(oProcess:oHTML:ValByName('It.cProDesc'), cProductDesc)

                    Aadd(oProcess:oHTML:ValByName('It.C8_QUANT'), Alltrim(STR(SC8->C8_QUANT,aTQuant[1],aTQuant[2])))
                    Aadd(oProcess:oHTML:ValByName('It.C8_QTDISP'), Alltrim(STR(SC8->C8_QTDISP,aTQtDisp[1],aTQtDisp[2])))
                    Aadd(oProcess:oHTML:ValByName('It.C8_PRECO'), Alltrim(STR(SC8->C8_PRECO ,aTPreco[1] ,aTPreco[2])))
                    Aadd(oProcess:oHTML:ValByName('It.C8_TOTAL'), Alltrim(STR(SC8->C8_TOTAL ,aTTotal[1] ,aTTotal[2])))
                    Aadd(oProcess:oHTML:ValByName('It.C8_OBS'), SC8->C8_OBS)
                EndIf

                SC8->(DbSkip())
            EndDo

            oProcess:oHTML:lUsaJS  := .F.

            oProcess:oWF:lHtmlBody := .T.
            oProcess:cTo := cNomeWF
            oProcess:UserSiga := cUserLog
            
            oProcess:NewVersion(.T.)

            cIDWF := oProcess:Start()

            oProcess:NewTask(cNomeWF, cDirWF + '\' + cHtmlMail2)

            oProcess:oHTML:ValByName('cNumCot'  , cNumCot)
            oProcess:oHTML:ValByName('cForNome' , cForNome)
            oProcess:oHtml:ValByName('proc_link', cSrLkWF + '/messenger/emp' + cEmpAnt + '/'+cNomeWF+'/' + cIDWF + '.htm')

            //Strings do template HTML nfcwfcustom2.html
            oProcess:oHTML:ValByName("cSTR1", DecodeUTF8(EncodeUTF8("Solicitação de Cotação")))
            oProcess:oHTML:ValByName("cSTR2", DecodeUTF8(EncodeUTF8("Solicitação de Cotação - Nº")))
            oProcess:oHTML:ValByName("cSTR3", DecodeUTF8(EncodeUTF8("Olá,")))
            oProcess:oHTML:ValByName("cSTR4", DecodeUTF8(EncodeUTF8("Você recebeu uma solicitação de cotação. Para visualizar e responder, acesse o link abaixo:")))
            oProcess:oHTML:ValByName("cSTR5", DecodeUTF8(EncodeUTF8("Abrir Cotação")))
            oProcess:oHTML:ValByName("cSTR6", DecodeUTF8(EncodeUTF8("Abrir cotação no navegador")))
            oProcess:oHTML:ValByName("cSTR7", DecodeUTF8(EncodeUTF8("Se o botão não funcionar, copie e cole este endereço no seu navegador:")))

            oProcess:cTo  := cEmail //-- E-mail do fornecedor
            oProcess:UserSiga := cUserLog
            oProcess:NewVersion(.T.)

            cIDLink := oProcess:Start()

            If lOk := !Empty(cIDWF) .And. !Empty(cIDLink)
                cMessage := "Workflow enviado com sucesso."
            Else
                cMessage := "Erro ao enviar o workflow para o fornecedor " + cForNome + "."
                Exit
            EndIf
        Next nX
    Else
        cMessage := "A cotação não foi localizada na base dados."
    EndIf

    //Retorne o código 200 para sucesso ou 400 para erro
    nCode := Iif(lOk, 200, 400)

    oJsonResp["code"] := nCode
    oJsonResp["message"] := cMessage

    aEval(aAreas, {|x| RestArea(x), FwFreeArray(x) })
    FwFreeArray(aTQuant)
    FwFreeArray(aTQtDisp)
    FwFreeArray(aTPreco)
    FwFreeArray(aTTotal)
Return oJsonResp

//Função de exemplo que recebe a resposta do fornecedor
User Function WfCustom(oWorkflow)
    Local cFilDHU       := PADR(AllTrim(oWorkflow:oHtml:RetByName('cFilCot')), TAMSX3("C8_FILENT")[1])  
    Local cNumQuote     := PADR(AllTrim(oWorkflow:oHtml:RetByName('cNumCot')), TAMSX3("C8_NUM")[1])
    Local cCodFornec    := PadR(RTrim(oWorkFlow:oHtml:RetByName('cFornece')), TAMSX3("C8_FORNECE")[1])
    Local cLoja         := PadR(RTrim(oWorkFlow:oHtml:RetByName('cLoja')), TAMSX3("C8_LOJA")[1])
    Local cNomeFornec   := PadR(RTrim(oWorkFlow:oHtml:RetByName('cForNome')), TAMSX3("C8_FORNOME")[1])
    Local cNumProposta  := PadR(RTrim(oWorkFlow:oHtml:RetByName('cNumProp')), TAMSX3("C8_NUMPRO")[1])
    Local cProduto      := ''
    Local cItem         := ''
    Local oModel        := nil
    Local oMasterDHU    := nil
    Local oGridSC8      := nil
    Local nX            := 0
    Local nPreco        := 0
    Local nQtdDisp      := 0
    
    DHU->( DbSetOrder(1) ) //DHU_FILIAL+DHU_NUM
    If DHU->(DbSeek(cFilDHU + cNumQuote))
    
        oModel   := FwLoadModel("NFCA020")
        oMasterDHU := oModel:GetModel("DHUMASTER")
        oGridSC8 := oModel:GetModel("SC8DETAIL")
        
        /*Chamar a seguinte função, informando número da cotação, código do fornecedor, nome do fornecedor e número da proposta, para que
        ocorra a inicialização correta dos objetos JSON da rotina. Se não fizer, ocorrerá erro, pois os objetos estarão vazios e é ESSENCIAL chamar a rotina.*/
        NF020SetSup(cNumQuote, cCodFornec, cLoja, cNomeFornec, cNumProposta)
    
        oModel:SetOperation(MODEL_OPERATION_UPDATE)   
        oModel:Activate()

        oMasterDHU:SetValue("DHU_COND", AllTrim(oWorkFlow:oHtml:RetByName('DHU_COND'))) //Condição de pagamento

        If !oModel:HasErrorMessage()
    
            //Editando os itens da cotação
            for nX := 1 to Len(oWorkFlow:oHtml:RetByName('It.C8_PRODUTO'))
                cProduto := oWorkFlow:oHtml:RetByName('It.C8_PRODUTO')[nX]
                cItem := oWorkFlow:oHtml:RetByName('It.C8_ITEM')[nX]

                If oGridSC8:SeekLine({{"C8_PRODUTO", cProduto}, {"C8_ITEM", cItem}})
                    nPreco := Val(oWorkFlow:oHtml:RetByName('It.C8_PRECO')[nX])
                    nQtdDisp := Val(oWorkFlow:oHtml:RetByName('It.C8_QTDISP')[nX])

                    oGridSC8:SetValue("C8_PRECO", nPreco)
                    oGridSC8:SetValue("C8_QTDISP", nQtdDisp)
                    
                    oGridSC8:SetValue("C8_OBS", oWorkFlow:oHtml:RetByName('It.C8_OBS')[nX])
                    oGridSC8:SetValue('C8_WF' , .T.) //Marca o item como respondido via workflow
                EndIf
            next nX

            //Calcular Impostos (Opcional)      
            NF020Calc()
        EndIf
    
        //Valido se o form está com informações corretas e consistentes
        if ( !oModel:HasErrorMessage() .And. oModel:VldData() )
            oModel:commitData()
        else
            //https://tdn.totvs.com/display/public/framework/FWFormModel - GetErrorMessage
            FwLogMsg("ERROR",,AllTrim(oModel:getErrorMessage()[5]),,,,AllTrim(oModel:getErrorMessage()[5]) + " - " + AllTrim(oModel:getErrorMessage()[6]) + AllTrim(oModel:getErrorMessage()[7]))
        endif
    
    endif
    
    oModel:DeActivate()
    oModel:Destroy()

    FWFreeObj(oModel)
    FWFreeObj(oGridSC8)
return nil

...