PI/NF-e: XPath como acelerador para regras de receiver determination
Tags:
Olá, pessoal,
Talvez não seja novidade para todos, mas acredito que o post a seguir pode sim ajudar algumas pessoas.
Recentemente estive junto com o @Perci Silva em um projeto fazendo a implementação do PI para atender as interfaces de NF-e. O ambiente já estava totalmente configurado para 4 estados, mas o requisito é que adicionalmente todas as SEFAZ e todos os serviços contemplados pelo SAP NFE fossem cobertos.
Iniciamos o trabalho de planejamento das atividades, e estimamos grosseiramente o seguinte:
25 novos parties (1 para cada SEFAZ + Ambiente Nacional + SVCs)
x
2 business services (homologação e produção)
x
6 canais de comunicação
=
~ 300 regras unívocas de roteamento para receiver determination
Acrescentando-se os mapping especiais de Bahia para SKIPR e SRVSC + o ajuste de outros objetos do cliente, chegamos a um número aproximado de 315 objetos a serem editados. Estimamos algo em torno de 15-20 minutos por objeto (considerando correções, eventual retrabalho, erros na ativação, etc), chegando ao tempo aproximado de ~80 horas de configuração ou ~ 2 semanas.
(Isso sem contar o tempo de documentação e assumindo que o ambiente de DEV estaria disponível e responsivo o tempo todo - pausa para sorriso sarcástico ).
Mas daí, olhando com mais atenção, surgiu a ideia de tentar melhorar isso, tanto para ganhar tempo quanto para facilitar a manutenção. Abaixo o passo-a-passo do que construímos:
1° agregar parties
A primeira medida que tomamos foi agregar parties o máximo possível. Como? Criando apenas 1 cadeia de party/service/cc para SVRS e outra para SVAN. Já vi muitas empresas (grandes, pequenas, médias, mas muitas) criando 1 cadeia para cada estado, mesmo aqueles atendidos pelas SEFAZ Virtuais.
O argumento que ouvi para isso foi: "caso a SEFAZ xpto decida sair do serviço virtual, a regra de roteamento já estará prevista e não precisaremos de um consultor PI para reconfigurar - basta mudar o endpoint".
Ok, o argumento é válido (apesar disso não ser muito frequente), mas vocês verão abaixo que isso deixa de ser um problema quando definirmos o condicional de roteamendo no receiver de maneira dinâmica com o XPath.
Primeiro ganho: Fazendo isso, com 2 cadeias já servimos 16 estados. Sobram os 11 estados com web service próprio + SVs + AN + SVC. Com essa simples medida caímos de 29 para 16 cadeias de objetos.
Segundo ganho: Outro ganho é que como o endpoint das SEFAZ Virtuais é um só, não é necessário ficar ajustando "n" objetos quando muda a URL do web service.
2° Incluir o <cUF> no nome do party
Se você ler rápido, vai parecer uma idea obcena. Mas não é ( ). A ideia aqui é que o nome do party contenha os 2 dígitos que identificam o estado. Aqui fizemos assim:
"NFE10_SEFAZ_<cUF>", o que nos deixou com os seguintes objetos:
Party | Estado |
---|---|
NFE10_SEFAZ_13 | AM |
NFE10_SEFAZ_29 | BA |
NFE10_SEFAZ_23 | CE |
NFE10_SEFAZ_52 | GO |
NFE10_SEFAZ_31 | MG |
NFE10_SEFAZ_50 | MS |
NFE10_SEFAZ_51 | MT |
NFE10_SEFAZ_26 | PE |
NFE10_SEFAZ_41 | PR |
NFE10_SEFAZ_43 | RS |
NFE10_SEFAZ_35 | SP |
NFE10_SEFAZ_SVRS | SVRS |
NFE10_SEFAZ_SVAN | SVAN |
NFE10_SEFAZ_SVC_RS | SVC-RS |
NFE10_SEFAZ_SVC_AN | SVC-AN |
NFE10_SEFAZ_AN | AN |
Ok... mas pra quê isso?
Terceiro ganho: Fazendo isso, para as SEFAZ próprias, poderemos determinar o party dinamicamente a partir do conteúdo do payload, utilizando uma expressão do XPath. Veremos em seguida.
3° Mapeamento de condições para expressões do XPath
Aqui é a parte que mais queimamos neurônio. O XPath, como a maioria já deve saber, nos permite manusear os condicionais de roteamento de maneira menos "engessaga" se comparada às expressões básicas que a interface do integration builder nos oferece.
Para entender melhor como isso funciona, li os seguintes conteúdos:
Customise your 'XPATH' Expressions in Receiver Determination (dica preciosa da Carolina Garcia, que não está no SCN, mas é feríssima do PI)
Xpath Condition in Receiver Determination - Process Integration - SCN Wiki
Using the Condition Editor - Integration Directory - SAP Library
(Também contei com a ajuda do jedi @Flavio Lazanha para refinar o entendimento)
Muito bem, entendida a tecnologia, partimos para a criação dos condicionais. Como tudo gira em torno de 3 campos-chave, todas as regras foram criadas com base neles:
- cUF
- tpAmb
- tpEmis
E como a grande variedade de possibilidades está no cUF, o condicional com expressões do XPath foi feito em cima deste campo, usando 2 expressões básicas. :
1) Validação da cUF desejada
/p1:<tipo de msg>[(p1:cUF = 'xx' or p1:cUF = 'yy' (...) or p1:cUF = 'zz')]
2) Eliminação das cUF indesejadas
/p1:<tipo de msg>[(not(p1:cUF = 'nn' or p1:cUF = 'mm' (...) or p1:cUF = 'jj'))]
Para não ocorrer múltiplos receivers, a "pergunta pro PI" tem que ter apenas 1 resposta possível. A resposta tem que dizer qual é a cUF em questão, univocamente. Para chegar nisso, então, montamos 6 expressões lógicas para mapearmos todas as possibilidades:
Pergunta | Expressão XPath |
---|---|
Validar SEFAZ própria ("=Prop") | /p1:<tipo de msg>[(p1:cUF = '13' or p1:cUF = '29' or p1:cUF = '23' or p1:cUF = '52' or p1:cUF = '31' or p1:cUF = '50' or p1:cUF = '51' or p1:cUF = '26' or p1:cUF = '41' or p1:cUF = '43' or p1:cUF = '35')] |
Excluir SEFAZ própria ("<>Prop") | /p1:<tipo de msg>[(not(p1:cUF = '13' or p1:cUF = '29' or p1:cUF = '23' or p1:cUF = '52' or p1:cUF = '31' or p1:cUF = '50' or p1:cUF = '51' or p1:cUF = '26' or p1:cUF = '41' or p1:cUF = '43' or p1:cUF = '35'))] |
Validar SVRS ("=SVRS") | /p1:NfeAutorizacaoLote[(p1:cUF = '13' or p1:cUF = '29' or p1:cUF = '23' or p1:cUF = '52' or p1:cUF = '31' or p1:cUF = '50' or p1:cUF = '51' or p1:cUF = '26' or p1:cUF = '41' or p1:cUF = '43' or p1:cUF = '35')] |
Excluir SVRS ("<>SVRS") | /p1:<tipo de msg>[(not(p1:cUF = '12' or p1:cUF = '27' or p1:cUF = '16' or p1:cUF = '53' or p1:cUF = '25' or p1:cUF = '33' or p1:cUF = '24' or p1:cUF = '11' or p1:cUF = '14' or p1:cUF = '42' or p1:cUF = '28' or p1:cUF = '32' or p1:cUF = '17'))] |
Validar SVAN ("=SVAN") | /p1:<tipo de msg>[(p1:cUF = '21' or p1:cUF = '15' or p1:cUF = '22')] |
Excluir SVAN ("<>SVAN") | /p1:<tipo de msg>[(not(p1:cUF = '21' or p1:cUF = '15' or p1:cUF = '22'))] |
Feito isso, passamos a configurar as regras de roteamento, que basicamente se concentraram em 3 grupos (sem contar SVCs e AN):
Regra | Condições XPath |
---|---|
Enviar para SEFAZ Própria | cUF = Prop AND <>SVRS AND <>SVAN |
Enviar para SVRS | cUF = SVRS AND <>SVAN AND <> Prop |
Enviar para SVAN | cUF = SVAN AND <>SVRS AND <> Prop |
O tpEmis e o tpAmb também devem ser considerados, mas sem expressões do XPath.
4° Implementação
A implementação é essencialmente uma atividade operacional. Só é preciso atenção para não errar na expressão lógica em cada caso, e lembrar de colocar as regras de tpEmis e tpAmb.
Abaixo, vou colocar o passo-a-passo de exemplo do receiver determination para estados com SEFAZ própria do cenário BATCH sem zip:
Importante: Antes de seguir adiante, tirei um backup da modelagem atual. Recomendo que façam o mesmo, just in case.
1) No editor de condições, escolha o operador lógico "EX"
2) Selecione o modo de entrada "XPath" e insira a expressão inteira lá
Exemplo: expressão para "= Prop".
3) Repita o processo para cada uma das expressões deste receiver, conforme a tabelinha anterior:
Exemplo: no caso, "= Prop AND <>SVRS AND <>SVAN":
4) Para determinar o party de destino da mensagem, insira uma expressão XPath de concatenação composto pela literal do nome + <cUF>:
concat('NFE10_SEFAZ_',/p1:<tipo de msg>/p1:cUF)
Quarto Ganho: com isso, basta 1 linha do receiver para determinar o roteamento de todas os estados com SEFAZ própria.
Nota: Para SVAN e SVRS não é necessário fazer o XPath pois a cUF não compõe o nome do party.
5) O resultado final será o seguinte:
Com 10 regras de roteamento cobrimos todas as possibilidades.
6) Comparativo antes e depois, por exemplo, para o cenário de BATSR:
Sexto Ganho: 10 objetos por cenário, ao invés de 29.
5° O Excel com o acelerador
Como comentei, a parte mais trabalhosa foi o passo 3 - chegar até as expressões unívocas de cada cenário.
Com o acelerador em mãos (link a seguir), o passo 4 é apenas repetição operacional e centenas de cliques.
Para quem se interessar em aplicar com esse modelo, o acelerador completo, com todas as regras e condicionais já mapeados, pode ser baixado aqui: Download NFE PI RecDet XPath
Considerações finais
Nos testes que efetuamos, não foram observadas alterações na performance. A etapa do pipeline de receiver determination continuou levando milisegundos.
Evidente que seguimos acompanhando, e se constatarmos que isso é um problema, é sempre bom ter um tpz com o modelo anterior de backup. Por isso, a recomendação lá em cima de tirar um snapshot da modelagem anterior.
A estimativa é que com essa abordagem, ao invés de ~315 atividades de manutenção de objetos, caiamos para algo em torno de 160, ou seja, uma economia de por volta de ~40h de trabalho. O que nos leva ao...:
Grande ganho: economia de tempo, recurso e dinheiro.
Quem se aventurar, dê um feedback, será muito bem-vindo!!
Abraços,
Eduardo Rubia