Skip to content

fix(nfse): correct NT007 social retentions and validate default description scope - #416

Merged
vitormattos merged 8 commits into
mainfrom
fix/nt007-social-retention-and-description-scope-20261010
Oct 12, 2026
Merged

vitormattos merged 8 commits into
mainfrom
fix/nt007-social-retention-and-description-scope-20261010

Conversation

@vitormattos

@vitormattos vitormattos commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

Diagnóstico

Revisão dos XMLs e da documentação federal: a NT SE/CGNFS-e 007/2026 (p. 6) determina que vRetCSLL seja a soma das retenções efetivas de PIS, COFINS e CSLL selecionadas em tpRetPisCofins, apesar da nomenclatura histórica. O PR #413 incorretamente passou a enviar apenas a parcela individual de CSLL, provocando E0724 quando tpRetPisCofins=4 e PIS/COFINS foram retidos.

O cenário de regressão é uma operação com retenções efetivas de PIS e COFINS, sem CSLL retida. A NT007 determina que vRetCSLL transporte a soma das contribuições sociais retidas selecionadas em tpRetPisCofins, sem criar CSLL individual fictícia. Os valores de casos reais não são reproduzidos nesta descrição.

Correção proposta

  • Restaurar FederalSocialRetentionCalculator::calculate(... )['total'] como valor destinado a federalValorCsll.
  • Preservar a separação de valores de apuração própria (vPis / vCofins) e contribuições efetivamente retidas.
  • Atualizar expectativas de testes, incluindo cenário realista de retenção apenas de PIS/COFINS, tipo 3 com CSLL e proteção contra retenções fictícias criadas a partir de alíquotas.
  • Testar que reemissão de recibo cancelado mantém os campos federais ao gerar a nova DPS e que a substituição delega ao mesmo caminho de emissão.
  • Rejeitar nfse_description_scope inválido sem erro interno, preservando validação de escopo e resposta traduzida em emit e reemit.
  • Complementar testes da persistência por cliente sem modificar o padrão geral.

Homologação do formulário de reemissão — diagnóstico da falha persistente

A tela podia mostrar "Padrão para todos os clientes" e mesmo assim produzir Invalid NFS-e description scope. O formulário dinâmico do Akaunting cria seu objeto Form lendo o atributo value dos selects HTML e serializa esse objeto, não necessariamente o valor selecionado no DOM. O select anterior não declarava value nem vinculava a mudança a form.nfse_description_scope; a requisição enviava valor vazio.

Correção UX/contrato: o modal compartilhado de emissão e reemissão agora utiliza um único select reativo nfse_description_save_mode, com três opções: none (padrão; não salva), general (todos os clientes da empresa atual) e customer (somente este cliente). O atributo value="none" inicializa corretamente o formulário do Akaunting e v-model mantém o envio sincronizado com o select visível. Os caminhos anteriores da listagem com nfse_save_default_description + nfse_description_scope continuam aceitos, com validação de escopo e fronteiras de empresa.

Testes acrescentados: persistência geral, recusa de salvamento padrão, isolamento por cliente e empresa, rejeição sem transmitir nova NFS-e e captura do POST real no modal E2E (alternância de opções, preenchimento do e-mail e comprovação de nfse_description_save_mode=general).

A interface da listagem continua no modelo anterior por compatibilidade; sua refatoração visual poderá ocorrer separadamente. Não há transmissão fiscal real automatizada neste PR.

Cobertura E2E: e2e/nfse-invoice-show-emit-modal.spec.ts comprovou a serialização do formulário e modo de salvamento com transporte interceptado. Playwright Full UI do HEAD final: success, após revisão e atualização da baseline visual do seletor reativo. Há um cenário opcional de fixture marcado como skipped, não contado como aprovado.

País no DANFSe — ajuste integrado de exibição

No nfse-php #116, a revisão 8ed55aabad3077684dc5ab8fb1a41890065186c2 apresenta BR no DANFSe quando o código de município no XML é reconhecido na tabela IBGE e mantém cPaisPrestacao ausente para prestação doméstica (regra fiscal E0304). Não confundir derivação visual de BR com o preenchimento do XML. O composer.json e o teste de runtime fixam a nova revisão. Reinstalar o runtime 3rdparty em homologação; somente limpar cache não carrega a versão atualizada.

Dependência do nfse-php para homologação (pin exato)

  • Upstream: LibreCodeCoop/nfse-php#116, mesclado em 12/10/2026 (c55c627f65939105fd39dafcfd19841b296d6eba).
  • Commit upstream revisado: 8ed55aabad3077684dc5ab8fb1a41890065186c2.
  • 3rdparty/composer.json agora fixa dev-main#c55c627f65939105fd39dafcfd19841b296d6eba. O teste ScopedRuntimeComposerConfigTest confere tanto o manifesto quanto a revisão efetivamente instalada pelo Composer.
  • A suite de empacotamento confere a revisão instalada, além do pin no manifesto. Não usar o runtime ainda presente em main nem validar somente a lógica do módulo.
  • Na instalação de homologação, executar no diretório do módulo composer thirdparty:build:prod e conferir o source.reference por composer --working-dir=3rdparty show librecodeoop/nfse-php --format=json. O arquivo 3rdparty/composer.lock é local/não versionado; se apontar à revisão antiga e impedir o build, resolver essa divergência antes de repetir o build.
  • Limpar cache da aplicação com php artisan optimize:clear no diretório do Akaunting e reiniciar PHP/filas que mantêm OPcache conforme o ambiente, sem pressupor Docker.
  • Validar em ambiente de homologação restrita, sem transmissão real automatizada, emissão com retenções sintéticas de PIS/COFINS (tpRetPisCofins=4, vRetCSLL consolidado), descrição padrão geral/específica e substituição/reemissão com conferência de XML/estado fiscal. Não executar testes fiscais em produção.
  • A dependência do chore(docs): remove internal agent email notes file #116 e os conflitos com a main foram integrados em oito commits incrementais GPG/DCO, sem squash. CI integral do HEAD final concluída com sucesso, sem liberação da revisão formal exigida.

Integração e verificações

Dependência coordenada: nfse-php #116. Não mesclar nem implantar até passar CI, revisão e homologação local sem transmissão real. Antes de reemitir/substituir qualquer NFS-e, consultar estado atual na SEFIN para evitar duplicações. O teste de substituição cobre o delegado interno; não substitui teste integrado do XML com o recibo efetivo.

Fontes oficiais

  • Nota Técnica SE/CGNFS-e nº 007/2026, página 6 — totalização das retenções sociais em vRetCSLL.
  • NT nº 008/2026 — seção Contribuições Sociais – Retidas no DANFSe.
  • Matriz de mudanças NT009, versionada em nfse-php/resources/contracts/nt009-dps-v1.04.01-matrix.tsv.

Nenhuma operação no gateway fiscal foi executada. Commits assinados com GPG e DCO.

Diagnóstico complementar — classificação e deduplicação fiscal

  • O commit assinado 4de5175 preserva linhas tributárias distintas com nome/valor coincidentes, sem tentar substituir a classificação fiscal tipada reservada à refactor: vincular identidade e papel fiscal aos impostos do Akaunting #428.
  • A classificação por nome (FederalTaxSnapshotBuilder::bucketFromName) ainda precisa evoluir para um contrato fiscal explícito por identidade de imposto, tipo de incidência e proveniência. A lacuna está coordenada pela issue #427 e pelas suas dependências; não significa que o presente PR resolva conformidade fiscal integral.
  • A investigação de relacionamentos Eloquent no CLI constatou efeitos de escopo de empresa sem sessão autenticada; isso, isoladamente, não demonstra perda de dados no fluxo HTTP. Não reproduzir identificadores de documentos operacionais nesta descrição.

Estado de integração em 12/10/2026

Nenhuma NFS-e real foi transmitida nesta integração, nenhuma nota histórica foi reemitida e nenhuma issue foi criada ou encerrada por este trabalho.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…axes

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…ntegration

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
@vitormattos
vitormattos force-pushed the fix/nt007-social-retention-and-description-scope-20261010 branch from af1e21a to 727e006 Compare October 12, 2026 18:48
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Reviewed Playwright artifact 11767985652 after replacing the legacy description toggle with the three-state save-mode select.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
@vitormattos
vitormattos marked this pull request as ready for review October 12, 2026 19:12

Copy link
Copy Markdown
Member Author

Revisão técnica da integração (12/10/2026) — HEAD 99498c1f19b0b18257d07d23077948c2f9a9abea.

A implementação foi reconstruída sobre a main que já contém os PRs #434, #435, #440, #441 e #442. Pin nfse-php: dev-main#c55c627f65939105fd39dafcfd19841b296d6eba; pacote efetivamente instalado validado na CI. Oito commits incrementais, todos verificados com assinatura GPG e DCO. Sem transmissão fiscal real.

Checks do HEAD final: PHPUnit 8.2/8.3/8.4, Psalm, PHP-CS, migrations, frontend, REUSE, Conventional Commits, DCO, Feature, Smoke e Playwright Full UI: aprovados. A única regressão foi a baseline visual deliberadamente alterada pelo seletor reativo; imagem e hash revisados no commit 99498c1. Dependabot aparece como skipped, não como teste aprovado. A NT SE/CGNFS-e 007 v1.0 (07/02/2026, efeitos em produção e produção restrita desde 09/02/2026) confirma a totalização de PIS/COFINS/CSLL efetivamente retidos em vRetCSLL, separada de vPis/vCofins.

Pendência para merge — governança, não código: ruleset #22483081 exige 1 aprovação e revisão por CODEOWNER, enquanto .github/CODEOWNERS contém somente * @vitormattos e este PR foi aberto por vitormattos. Não é possível satisfazer a revisão obrigatória por autoaprovação, e não há autorização para bypass administrativo. O PR está Ready for review, mas deve permanecer aberto até que o requisito seja resolvido por um fluxo legítimo e independente.

A classificação fiscal persistente por identidade e papel tributário segue fora deste PR (#428), assim como a matriz normativa mais ampla (#427).

@vitormattos
vitormattos merged commit 3739466 into main Oct 12, 2026
15 checks passed
@vitormattos
vitormattos deleted the fix/nt007-social-retention-and-description-scope-20261010 branch October 12, 2026 19:16
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