01. DADOS GERAIS
| Produto: | TOTVS Backoffice |
|---|---|
| Linha de Produto: | Linha Protheus |
| Segmento: | Backoffice |
| Módulo: | TOTVS Backoffice (Linha Protheus) - Compras (SIGACOM) |
| Função: | NFC - ENVIO DE WORKFLOW |
| País: | Brasil |
| Ticket: | 24289815 |
| Requisito/Story/Issue (informe o requisito relacionado) : | DBSUPINV-6054 |
02. DESCRIÇÃO
Descrição: Este ponto de entrada é utilizado para substituir a API de envio do workflow do NFC, podendo ser realizada qualquer implementação de workflow customizado.
Localização: NFC - Processos de envio do workflow (Geração da cotação, Envio de e-mail para o fornecedor, Novo participante e Nova proposta workflow).
Exemplos: Salvar os arquivos html com o título descrito no exemplo nfcwfcustom1.html e nfcwfcustom2.html
Importante
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.
#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
<!DOCTYPE html>
<html>
<head>
<meta charset="windows-1252">
<meta charset="UTF-8">
<title>%cSTR1%</title>
<style>
/* Estilos devem ficar inline nas tags */
</style>
</head>
<body style="font:14px Arial, sans-serif; margin:12px;">
<!-- Título -->
<h1 style="font-size:18px; margin:0 0 8px 0;">
%cSTR2% %cNumCot% %cSTR3% %cNumProp%
</h1>
<!-- Cabeçalho -->
<table style="width:100%; border-collapse:collapse;">
<tr>
<td style="border:1px solid #ccc; padding:6px; width:180px;">%cSTR4%</td>
<td style="border:1px solid #ccc; padding:6px;">%cForNome%</td>
</tr>
<tr>
<td style="border:1px solid #ccc; padding:6px;">%cSTR5%</td>
<td style="border:1px solid #ccc; padding:6px;">%cFornece% / %cLoja%</td>
</tr>
<tr>
<td style="border:1px solid #ccc; padding:6px;">%cSTR6%</td>
<td style="border:1px solid #ccc; padding:6px;">%cFilCot%</td>
</tr>
</table>
<!-- Itens -->
<form method="post" action="mailto:%25WFMailTo%25" style="margin:0; padding:0;">
<h2 style="font-size:16px; margin:12px 0 6px 0;">%cSTR7%</h2>
<table style="width:100%; border-collapse:collapse;">
<thead>
<tr>
<th style="border:1px solid #ccc; padding:6px; text-align:left;">%cSTR8%</th>
<th style="border:1px solid #ccc; padding:6px; text-align:left;">%cSTR9%</th>
<th style="border:1px solid #ccc; padding:6px; text-align:left;">%cSTR10%</th>
<th style="border:1px solid #ccc; padding:6px; text-align:right;">%cSTR11%</th>
<th style="border:1px solid #ccc; padding:6px; text-align:right;">%cSTR12%</th>
<th style="border:1px solid #ccc; padding:6px; text-align:right;">%cSTR13%</th>
<th style="border:1px solid #ccc; padding:6px; text-align:right;">%cSTR14%</th>
<th style="border:1px solid #ccc; padding:6px; text-align:left;">%cSTR15%</th>
</tr>
</thead>
<tbody>
<!-- Linha repetida pelo mecanismo do Workflow para cada item -->
<tr class="item">
<td style="border:1px solid #ccc; padding:6px;">%It.C8_ITEM%</td>
<td style="border:1px solid #ccc; padding:6px;">%It.C8_PRODUTO%</td>
<td style="border:1px solid #ccc; padding:6px;">%It.cProDesc%</td>
<!-- Quantidade (numérico, somente leitura) -->
<td style="border:1px solid #ccc; padding:6px; text-align:right;">
<input type="number" name="It.C8_QUANT" class="C8_QUANT"
value="%It.C8_QUANT%" step="0.01" min="0" readonly
style="width:100%; height:28px; box-sizing:border-box; text-align:right; background:#f9f9f9;">
</td>
<!-- Qtde Disponível (numérico) -->
<td style="border:1px solid #ccc; padding:6px; text-align:right;">
<input type="number" name="It.C8_QTDISP" class="C8_QTDISP"
value="%It.C8_QTDISP%" step="0.01" min="0" oninput="gt(this)"
style="width:100%; height:28px; box-sizing:border-box; text-align:right;">
</td>
<!-- Preço Unitário (numérico) -->
<td style="border:1px solid #ccc; padding:6px; text-align:right;">
<input type="number" name="It.C8_PRECO" class="C8_PRECO"
value="%It.C8_PRECO%" step="0.01" min="0" oninput="gt(this)"
style="width:100%; height:28px; box-sizing:border-box; text-align:right;">
</td>
<!-- Total (numérico, calculado) -->
<td style="border:1px solid #ccc; padding:6px; text-align:right;">
<input type="number" name="It.C8_TOTAL" class="C8_TOTAL"
value="%It.C8_TOTAL%" step="0.01" min="0" readonly
style="width:100%; height:28px; box-sizing:border-box; text-align:right; background:#f9f9f9;">
</td>
<!-- Observação (texto) -->
<td style="border:1px solid #ccc; padding:6px;">
<input type="text" name="It.C8_OBS" class="C8_OBS" value="%It.C8_OBS%"
style="width:100%; height:28px; box-sizing:border-box;">
</td>
</tr>
</tbody>
</table>
<!-- Hidden essentials -->
<input type="hidden" name="cFilCot" value="%cFilCot%">
<input type="hidden" name="cNumCot" value="%cNumCot%">
<input type="hidden" name="cFornece" value="%cFornece%">
<input type="hidden" name="cLoja" value="%cLoja%">
<input type="hidden" name="cForNome" value="%cForNome%">
<input type="hidden" name="cNumProp" value="%cNumProp%">
<!-- Rodapé (condição + enviar) -->
<table style="width:100%; margin-top:10px;">
<tr>
<td style="padding:6px; vertical-align:middle;">
<label for="DHU_COND" style="margin-right:6px; font-weight:bold;">%cSTR17%</label>
<input type="text" name="DHU_COND" id="DHU_COND" value="%DHU_COND%"
style="width:240px; height:28px; box-sizing:border-box;">
</td>
<td style="padding:6px; text-align:right; vertical-align:middle;">
<button type="submit"
style="min-width:140px; height:34px; border:1px solid #888; background:#eee; cursor:pointer;">
%cSTR16%
</button>
</td>
</tr>
</table>
</form>
<!-- JS: Total = Preço × Qtde Disponível (linha atual) -->
<script>
function gt(el){
var node = el;
while (node && node.tagName !== 'TR') node = node.parentNode;
if(!node) return;
var qty = node.querySelector('.C8_QTDISP');
var prc = node.querySelector('.C8_PRECO');
var tot = node.querySelector('.C8_TOTAL');
var q = parseFloat(((qty && qty.value) || '0').replace(',', '.'));
var p = parseFloat(((prc && prc.value) || '0').replace(',', '.'));
if (isNaN(q)) q = 0;
if (isNaN(p)) p = 0;
var val = q * p;
if (tot) tot.value = val.toFixed(2);
}
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>%cSTR1%</title>
<style>
/* estilos devem ficar inline nas tags; bloco vazio proposital */
</style>
</head>
<body style="font:14px Arial, sans-serif; margin:12px;">
<!-- Título -->
<h1 style="font-size:18px; margin:0 0 8px 0;">%cSTR2% %cNumCot%</h1>
<!-- Mensagem -->
<div style="border-top:1px solid #ccc; padding-top:10px; margin-top:10px;">
<p style="margin:0 0 10px 0; line-height:1.4;">
%cSTR3% <strong>%cForNome%</strong>. %cSTR4%
</p>
</div>
<!-- Botão / CTA -->
<div style="margin:10px 0;">
<a href="!proc_link!" title="%cSTR6%"
style="display:inline-block; padding:8px 14px; border:1px solid #888; background:#eee; text-decoration:none; color:#000;">
%cSTR5%
</a>
</div>
<!-- Fallback de link em texto -->
<div style="margin:0 0 20px 0; font-size:13px; color:#333;">
%cSTR7%<br>
<span style="word-break:break-all;">!proc_link!</span>
</div>
</body>
</html>
03. DEMAIS INFORMAÇÕES
Quando este ponto de entrada está ativado, a tela de envio do workflow da cotação é resumida para conter apenas a opção de preenchimento dos e-mails e se envia ou não o workflow, não sendo possível utilizar todas as funcionalidades originais do workflow padrão.
Para receber o retorno do workflow customizado, é necessário utilizar a rotina automática NFCA020 conforme a documentação do Guia de referência - Novo Fluxo de Compras presente na sessão 07. PONTOS DE ENTRADA E ROTINA AUTOMÁTICA > Rotina automática - Edição da cotação.
04. ASSUNTOS RELACIONADOS
Guia de referência - Novo Fluxo de Compras