root@construct:~/projects/cte$
<-- voltar para /projects

Conferência de CT-e

Conferência de CT-e para uma grande operação logística

PythonPlaywright

>Contexto

Um escritório contábil confere todo mês os CT-e, os conhecimentos de transporte eletrônicos, dos clientes transportadores. Uma das fontes é o portal de uma grande operação logística. Hoje a conferência é à mão: baixar os XMLs, importar no sistema contábil e comparar os relatórios para ver se o total bate.

Esta prova de conceito automatiza a conferência. Ela compara o relatório do portal com os XMLs do mesmo período e responde, documento por documento, OK, DIVERGENTE ou NÃO CONFERIDO. Um conector somente leitura entra no portal, baixa o relatório e o lote de XMLs e já roda a conferência. Ele rodou no portal real.

Construí entre 30 de setembro e 20 de outubro de 2026, em 62 commits. Depois, a prova de conceito virou um piloto ponta a ponta, ainda em andamento: captura em três fontes, importação no sistema contábil e conferência dos três lados.

>Arquitetura (HLD)

Tudo roda no PC Windows do escritório, como agente local: Python 3.13 num ambiente próprio, com o Chromium do Playwright. Um script PowerShell instala tudo com versões fixas e confere o SHA-256 de cada download; rodar de novo não duplica nada.

A rodada começa pelo botão do painel ou pelo Agendador de Tarefas, que recupera a data perdida se o PC estava desligado. Primeiro o atualizador vê se há versão nova. Depois o conector entra no portal só para ler: faz login, gera o relatório, baixa o lote de XMLs e compara a quantidade baixada com o contador da tela. Os arquivos vão para uma pasta por rodada e cliente. Os leitores levam relatório e XMLs ao mesmo modelo, e o comparador devolve OK, DIVERGENTE ou NÃO CONFERIDO para cada documento. O resultado sai em resumo, CSV, JSON e planilha e segue por e-mail, via SMTP. No piloto, a mesma rodada também importa a pasta no sistema contábil, que roda em nuvem.

O estado fica no disco do PC: as pastas das rodadas, o histórico e logs sem segredos. As senhas ficam no Gerenciador de Credenciais do Windows, e o cadastro dos clientes só na máquina, nunca no repositório. Além do agendamento, nada é assíncrono: não há fila nem servidor no meio. As atualizações saem como um pacote zip e um manifesto assinado numa hospedagem estática. O robô recusa o pacote se a assinatura ou o SHA-256 não batem, troca só os arquivos do programa e volta à versão anterior se a nova não passar no teste rápido.

Passe o mouse ou foque uma peça: ela acende com as ligações.
quem usaPC do escritório (Windows)serviços externos2 Painel de um botão1 Equipe do escritório5 Rodada de conferência3 Agendador de Tarefas7 Conector do portal4 Cofre de credenciais10 Portal logístico8 Pasta de XMLs6 Atualizador12 E-mail do resultado11 Sistema contábil9 Resultado13 Hospedagem estática
13 peças13 ligações3 áreas

Componentes

  • Painel e agendamento :: Janela de um botão no PC do escritório e uma tarefa no Agendador do Windows que roda nas datas combinadas e recupera a data perdida.
  • Conector do portal :: Playwright, só leitura: login, relatório, lote de XMLs, retentativa com modal travado, divisão do mês em semanas e contagem pela tela.
  • Leitores plugáveis :: Levam Excel (binário e HTML), xlsx, CSV, PDF e XMLs em pasta ou zip para o mesmo modelo de documento.
  • Comparador :: Aplica as regras documento por documento e devolve OK, DIVERGENTE ou NÃO CONFERIDO, sempre com o motivo.
  • Saída e e-mail :: Resumo em português, CSV, JSON, planilha e código de saída 0, 1 ou 2; o e-mail sai por SMTP com a planilha anexa e sem XML.
  • Cofre de credenciais :: As senhas dos portais ficam no Gerenciador de Credenciais do Windows; mensagens de erro citam só o nome do segredo, nunca o valor.
  • Atualizador assinado :: Antes de cada rodada baixa o manifesto de uma hospedagem estática, confere assinatura e SHA-256, troca só o código e volta atrás se o teste rápido falha.

>Trade-offs

Três estados, com NÃO CONFERIDO para tudo o que não deu para verificar.

Alternativa descartada: Só OK ou DIVERGENTE.

Por quê: Para um contador, uma automação que diz OK sem ter conferido é pior que o processo manual. A primeira versão devolvia OK em pelo menos 4 situações erradas, entre elas captura vazia e CT-e com evento de cancelamento.

Conector somente leitura, que se recusa a clicar em botões que alteram o portal.

Alternativa descartada: Automação livre da tela, inclusive salvar o layout do relatório.

Por quê: É regra fixa do projeto: nos portais, só leitura e download.

Comparar a quantidade baixada com o contador da tela do portal e gerar o relatório de novo se não bater.

Alternativa descartada: Confiar no arquivo baixado.

Por quê: Numa execução o relatório veio com mais linhas do que CT-e válidos. Se a contagem segue diferente, o resultado é NÃO CONFERIDO.

CT-e de complemento numa categoria própria, com quantidade e soma.

Alternativa descartada: Misturar os complementos com as outras divergências.

Por quê: O filtro padrão do relatório não lista complementos. No mês inteiro, os CT-e a mais eram todos complementos; separados, a divergência fica explicada.

Rodar como agente local no computador do escritório.

Alternativa descartada: App na nuvem que recebe os arquivos por upload.

Por quê: A pasta de XMLs e o sistema contábil ficam na máquina do escritório, e um mês de XMLs pesa: 15 mil XMLs sintéticos mínimos já dão 5,9 MB zipados.

>Destaques

  • >Rodou no portal real, só leitura: OK em todos os CT-e de 01 a 04/09/2026
  • >Setembro de 2026 inteiro: OK em todos os CT-e, complementos incluídos
  • >15 mil XMLs cruzados com 15 mil linhas de relatório em 0,8 s, com dados sintéticos
  • >504 testes, com um portal falso local que imita os rótulos e o modal do real
  • >62 commits entre 30/09 e 20/10/2026

>Curiosidades

  • *O pdftotext 25 perde um caractere quando dois valores se encostam no PDF. O leitor recompõe o valor, e a soma do rodapé continua conferida, então uma recomposição errada não vira OK.
  • *Um teste injeta 65 linhas extras no relatório real de setembro, e o resultado não muda.
  • *Em 11 execuções reais houve 3 falhas intermitentes: 2 cliques travados pelo modal 'Processando, aguarde...' e 1 download que passou de 180 s.
  • *Regra do projeto: nenhum arquivo novo passa de 400 linhas.
Conferência de CT-e | The Broad Way | Kinho.dev