No artigo de hoje, vou mostrar como fazer um ponto de entrada em MVC, e que dispare um e-Mail ao incluir / alterar / excluir o registro.
Basicamente a lógica jovens, é interceptar a operação antes de fazer o commit, e montar 3 mensagens diferentes dependendo da operação realizada.
E na alteração, o que fazemos é pegar a estrutura da tabela com DbStruct, então fazemos um laço de repetição comparando o valor antigo com o novo, caso seja diferente será adicionado em uma tabela em HTML.
Abaixo um print do e-Mail de inclusão.
Abaixo um print do e-Mail de alteração.
E abaixo um print do e-Mail de exclusão.
Por último, abaixo o código fonte desenvolvido:
//Bibliotecas
#Include "TOTVS.ch"
/*/{Protheus.doc} User Function MATA070
P.E. no Cadastro de Bancos
@author Atilio
@since 02/07/2021
@version 1.0
@type function
@obs Salve o arquivo como MATA070_pe.prw
/*/
User Function MATA070()
Local aArea := GetArea()
Local aParam := PARAMIXB
Local xRet := .T.
Local oObj := Nil
Local cIdPonto := ''
Local cIdModel := ''
Local nOper := 0
Local cPara := Alltrim(SuperGetMV("MV_X_EMBCO", .F., ""))
Local cMensagem := ''
Local cAssunto := ''
//Se tiver parâmetros
If aParam != Nil
//Pega informações dos parâmetros
oObj := aParam[1]
cIdPonto := aParam[2]
cIdModel := aParam[3]
//Validação ao clicar no Botão Confirmar
If cIdPonto == 'MODELPOS'
nOper := oObj:nOperation
cMensagem := ''
xRet := .T.
//Se for uma inclusão
If nOper == 3
cAssunto := "[Protheus] Inclusão no Cadastro de Bancos"
cMensagem := fMensInc()
//Se for uma alteração
ElseIf nOper == 4
cAssunto := "[Protheus] Alteração no Cadastro de Bancos"
cMensagem := fMensAlt()
//Se for uma exclusão
ElseIf nOper == 5
cAssunto := "[Protheus] Exclusão no Cadastro de Bancos"
cMensagem := fMensExc()
EndIf
u_zEnvMail(cPara, cAssunto, cMensagem)
EndIf
EndIf
RestArea(aArea)
Return xRet
Static Function fMensInc()
Local aArea := GetArea()
Local cMensagem := ""
cMensagem += "<p>Olá.</p>" + CRLF
cMensagem += "" + CRLF
cMensagem += "<p>Um novo Banco <strong>foi cadastrado</strong> no Protheus, abaixo as principais informações cadastradas:</p>" + CRLF
cMensagem += "" + CRLF
cMensagem += "<ul>" + CRLF
cMensagem += "<li>Código:" + FWFldGet("A6_COD") + "</li>" + CRLF
cMensagem += "<li>Agência:" + FWFldGet("A6_AGENCIA") + "-" + FWFldGet("A6_DVAGE") + "</li>" + CRLF
cMensagem += "<li>Conta:" + FWFldGet("A6_NUMCON") + "-" + FWFldGet("A6_DVCTA") + "</li>" + CRLF
cMensagem += "<li>Nome do Banco:" + FWFldGet("A6_NOME") + "</li>" + CRLF
cMensagem += "</ul>" + CRLF
cMensagem += "" + CRLF
cMensagem += "<p>e-Mail gerado automaticamente pelo Protheus no dia '" + dToC(Date()) + "' às '" + Time() + "'.</p>" + CRLF
RestArea(aArea)
Return cMensagem
Static Function fMensExc()
Local aArea := GetArea()
Local cMensagem := ""
cMensagem += "<p>Olá.</p>" + CRLF
cMensagem += "" + CRLF
cMensagem += "<p>O Banco citado abaixo foi excluído da base de dados do sistema:</p>" + CRLF
cMensagem += "" + CRLF
cMensagem += "<ul>" + CRLF
cMensagem += "<li>Código:" + FWFldGet("A6_COD") + "</li>" + CRLF
cMensagem += "<li>Agência:" + FWFldGet("A6_AGENCIA") + "-" + FWFldGet("A6_DVAGE") + "</li>" + CRLF
cMensagem += "<li>Conta:" + FWFldGet("A6_NUMCON") + "-" + FWFldGet("A6_DVCTA") + "</li>" + CRLF
cMensagem += "<li>Nome do Banco:" + FWFldGet("A6_NOME") + "</li>" + CRLF
cMensagem += "</ul>" + CRLF
cMensagem += "" + CRLF
cMensagem += "<p>e-Mail gerado automaticamente pelo Protheus no dia '" + dToC(Date()) + "' às '" + Time() + "'.</p>" + CRLF
RestArea(aArea)
Return cMensagem
Static Function fMensAlt()
Local aArea := GetArea()
Local cMensagem := ""
Local aEstrut := SA6->(DbStruct())
Local nAtual := 0
Local cCampo
Local xContAnt
Local xContNov
cMensagem += "<p>Olá.</p>" + CRLF
cMensagem += "" + CRLF
cMensagem += "<p>O Banco citado abaixo teve alterações no sistema:</p>" + CRLF
cMensagem += "" + CRLF
cMensagem += "<ul>" + CRLF
cMensagem += "<li>Código:" + FWFldGet("A6_COD") + "</li>" + CRLF
cMensagem += "<li>Agência:" + FWFldGet("A6_AGENCIA") + "-" + FWFldGet("A6_DVAGE") + "</li>" + CRLF
cMensagem += "<li>Conta:" + FWFldGet("A6_NUMCON") + "-" + FWFldGet("A6_DVCTA") + "</li>" + CRLF
cMensagem += "<li>Nome do Banco:" + FWFldGet("A6_NOME") + "</li>" + CRLF
cMensagem += "</ul>" + CRLF
cMensagem += "" + CRLF
cMensagem += "<p>Abaixo as alterações efetuadas:</p>" + CRLF
cMensagem += "<table border='1'>" + CRLF
cMensagem += " <thead>" + CRLF
cMensagem += " <tr>" + CRLF
cMensagem += " <th><strong>Campo</strong></th>" + CRLF
cMensagem += " <th><strong>Descrição</strong></th>" + CRLF
cMensagem += " <th><strong>Conteúdo Antigo</strong></th>" + CRLF
cMensagem += " <th><strong>Conteúdo Novo</strong></th>" + CRLF
cMensagem += " </tr>" + CRLF
cMensagem += " </thead>" + CRLF
cMensagem += " <tbody>" + CRLF
//Percorre todos os campos da estrutura da tabela
For nAtual := 1 To Len(aEstrut)
cCampo := aEstrut[nAtual][1]
cAssunto := GetSX3Cache(cCampo, "X3_TITULO")
xContAnt := &("SA6->" + cCampo)
xContNov := FWFldGet(cCampo)
//Se a informação digitada pelo usuário for diferente da cadastrada
If xContAnt != xContNov .And. xContNov != Nil
cMensagem += " <tr>" + CRLF
cMensagem += " <td>" + cCampo + "</td>" + CRLF
cMensagem += " <td>" + cAssunto + "</td>" + CRLF
cMensagem += " <td>" + Iif(aEstrut[nAtual][2] != "C", cValToChar(xContAnt), xContAnt) + "</td>" + CRLF
cMensagem += " <td>" + Iif(aEstrut[nAtual][2] != "C", cValToChar(xContNov), xContNov) + "</td>" + CRLF
cMensagem += " </tr>" + CRLF
EndIf
Next
cMensagem += " </tbody>" + CRLF
cMensagem += "</table>" + CRLF
cMensagem += "<p>e-Mail gerado automaticamente pelo Protheus no dia '" + dToC(Date()) + "' às '" + Time() + "'.</p>" + CRLF
RestArea(aArea)
Return cMensagem
Esse artigo foi uma sugestão de tema enviada pelo grande Hitler Almeida.
Obs.: A função zEnvMail para disparo de e-Mail pelo Protheus, está disponível nesse artigo – clique aqui.
Obs. 2: O ideal é pegar o valor dos campos usando GetValue no Model, porém para título de exemplo, eu usei a função FWFldGet no trecho de fonte acima
Bom pessoal, por hoje é só.
Abraços e até a próxima.



Daniel, bom dia.
Você é um verdade mestre e professor que nos ajuda muito.
Mas nesse artigo vou dar uma sugestão ao invés de fazer 3 Static Function controla pelo nOper e faz uma única Static Function (sei também que os leitores pode fazer isso ou mesmo modificar outras).
Muito obrigado por mais um artigo.
Grande Fábio, primeiramente obrigado pelo elogio, é muita generosidade sua.
Sim, eu havia pensado em fazer 1 só, mas decide segregar em 3 para ficar mais fácil de exemplificar.
Um grande abraço e eu quem agradeço pelo comentário.