Skip to content

feat(documentos): extrair dados fiscais do XML e filtrar por CFOP, NC… - #27

Merged
net0well merged 1 commit into
mainfrom
feature/017-filtros-fiscais
Jul 29, 2026
Merged

net0well merged 1 commit into
mainfrom
feature/017-filtros-fiscais

Conversation

@net0well

Copy link
Copy Markdown
Owner

…M e CST

O XML baixado não abria em leitor nenhum, e a nota na tela não dizia nada além de valor e participantes. As duas coisas têm a mesma origem: o arquivo arquivado nunca era lido.

XML arquivado compactado

A Distribuição DF-e entrega cada documento no elemento docZip — o XML comprimido em gzip e codificado em base64. A biblioteca fiscal decodifica o base64 para mont

A captura passa a descompactar antes de arquivar. A leitura também descompacta, porque o acervo gravado por versões anteriores continua no bucket — a conferência custa três bytes e garante que ninguém receba arquivo quebrado por ter baixado antes da varredura. Fluxo truncado é tratado à parte: o GZipStream lê o cabeçalho, não encontra bloco algum e devolve zero bytes sem lançar, o que faria o reprocessamento regravar o objeto vazio e apagar o XML em silêncio.

Dados fiscais

TotaisFiscais traz os dez valores de ICMSTot por composição na própria tabela de documentos; itens_documento_fiscal guarda as linhas de produto com CFOP, NCM, CEST, CST/CSOSN, quantidade, unitário e impostos. CFOP e NCM são de item, não de nota: uma NF-e com quarenta linhas pode carregar cinco CFOPs, e é por isso que o filtro pergunta por notas que contenham algum item com o código.

Um único extrator, por XDocument, serve à captura e ao reprocessamento. Fossem dois, a mesma nota capturada hoje e reprocessada amanhã divergiria no banco. Ele trata o grupo polimórfico do ICMS pegando o primeiro filho de <ICMS> — o que cobre ICMS00 a ICMS90 e ICMSSN101 a ICMSSN900 sem enumerar nenhum — e lê CSOSN onde não há CST, que é o caso de toda nota emitida por empresa do Simples.

TotaisFiscais.Vazios e DadosFiscaisDto.Vazio devolvem instância nova a cada chamada. Como tipo mapeado por composição, uma instância compartilhada entre dois documentos aparece para o EF Core como a mesma entidade mudando de dono, e a segunda gravação falha.

Reprocessamento do acervo

POST /jobs/reprocessar-acervo relê os XMLs já arquivados. Uma única leitura por documento resolve as duas coisas, porque é o mesmo arquivo: o XML que precisa ser lido para extrair CFOP e impostos é o mesmo que precisa sair do gzip. Não fala com a SEFAZ, então roda com o CNPJ bloqueado por consumo indevido. É reentrante — a segunda passada substitui os itens em vez de duplicá-los, que é como uma correção no extrator alcança o que já foi gravado.

Tela

O detalhe ganha natureza da operação, cartão de impostos e a tabela de itens. Quando o XML existe mas ainda não foi lido, a tela diz isso em vez de mostrar zeros — zero seria lido como fato. A grade ganha os filtros de CFOP, NCM, CST e ST; CFOP e NCM buscam por prefixo, que é como a classificação fiscal é organizada e como o contador digita.

Filtro de item exclui em silêncio toda nota que ficou no resumo, porque resumo não tem item nenhum. A grade informa quantos documentos do período ficaram de fora por isso — sem o aviso, o contador conclui que a nota sumiu do sistema.

…M e CST

O XML baixado não abria em leitor nenhum, e a nota na tela não dizia nada além de valor
e participantes. As duas coisas têm a mesma origem: o arquivo arquivado nunca era lido.

XML arquivado compactado

A Distribuição DF-e entrega cada documento no elemento `docZip` — o XML comprimido em
gzip e codificado em base64. A biblioteca fiscal decodifica o base64 para mont

A captura passa a descompactar antes de arquivar. A leitura também descompacta, porque o
acervo gravado por versões anteriores continua no bucket — a conferência custa três bytes
e garante que ninguém receba arquivo quebrado por ter baixado antes da varredura. Fluxo
truncado é tratado à parte: o `GZipStream` lê o cabeçalho, não encontra bloco algum e
devolve zero bytes sem lançar, o que faria o reprocessamento regravar o objeto vazio e
apagar o XML em silêncio.

Dados fiscais

`TotaisFiscais` traz os dez valores de `ICMSTot` por composição na própria tabela de
documentos; `itens_documento_fiscal` guarda as linhas de produto com CFOP, NCM, CEST,
CST/CSOSN, quantidade, unitário e impostos. CFOP e NCM são de item, não de nota: uma NF-e
com quarenta linhas pode carregar cinco CFOPs, e é por isso que o filtro pergunta por
notas que **contenham** algum item com o código.

Um único extrator, por `XDocument`, serve à captura e ao reprocessamento. Fossem dois, a
mesma nota capturada hoje e reprocessada amanhã divergiria no banco. Ele trata o grupo
polimórfico do ICMS pegando o primeiro filho de `<ICMS>` — o que cobre `ICMS00` a `ICMS90`
e `ICMSSN101` a `ICMSSN900` sem enumerar nenhum — e lê `CSOSN` onde não há `CST`, que é o
caso de toda nota emitida por empresa do Simples.

`TotaisFiscais.Vazios` e `DadosFiscaisDto.Vazio` devolvem instância nova a cada chamada.
Como tipo mapeado por composição, uma instância compartilhada entre dois documentos
aparece para o EF Core como a mesma entidade mudando de dono, e a segunda gravação falha.

Reprocessamento do acervo

`POST /jobs/reprocessar-acervo` relê os XMLs já arquivados. Uma única leitura por documento
resolve as duas coisas, porque é o mesmo arquivo: o XML que precisa ser lido para extrair
CFOP e impostos é o mesmo que precisa sair do gzip. Não fala com a SEFAZ, então roda com o
CNPJ bloqueado por consumo indevido. É reentrante — a segunda passada substitui os itens
em vez de duplicá-los, que é como uma correção no extrator alcança o que já foi gravado.

Tela

O detalhe ganha natureza da operação, cartão de impostos e a tabela de itens. Quando o XML
existe mas ainda não foi lido, a tela diz isso em vez de mostrar zeros — zero seria lido
como fato. A grade ganha os filtros de CFOP, NCM, CST e ST; CFOP e NCM buscam por prefixo,
que é como a classificação fiscal é organizada e como o contador digita.

Filtro de item exclui em silêncio toda nota que ficou no resumo, porque resumo não tem
item nenhum. A grade informa quantos documentos do período ficaram de fora por isso — sem
o aviso, o contador conclui que a nota sumiu do sistema.
@net0well
net0well merged commit b036a08 into main Jul 29, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant