Files
GTI_GERENCIADOR_FISCAL/docs/unified_fiscal_completeness.md
T
gtiandClaude Sonnet 5 b15dbea213 feat: unified fiscal coverage - PIS/COFINS applicability + conditional RTC in one definition, one queue, one panel
- central/app/unified_fiscal_coverage.py: pure rules (PIS/COFINS NOT_APPLICABLE/REQUIRED/OPTIONAL/NEEDS_REVIEW, RTC only when the ERP switch is on)
- agent: read-only loader (unified_fiscal.py) replaces the legacy/expanded module; findings feed the single operational state, coverage and blocker queue
- hub: BLOCKED_FISCAL_DATA blockers (PIS/COFINS/RTC) share the queue; stale ones close on the next full pass; dashboard breakdown gains CEST/PIS/COFINS/RTC
- panel: legacy/expanded coverage block removed; discreet 'Reforma Tributaria: Ativa/Desativada'
- docs: unified_fiscal_completeness, pis_cofins_applicability, rtc_pis_cofins_model + official source manifests; read-only E2E script

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 16:39:53 -03:00

5.1 KiB
Raw Blame History

Completude fiscal unificada (UNIFIED_FISCAL_COVERAGE)

Uma definição de "completo", um painel, uma fila de blockers, uma cobertura.

Definição

campos obrigatórios(produto, empresa) =
    campos fiscais base aplicáveis (NCM, CEST, CFOP, ICMS/CST/CSOSN, IPI ... — decididos pelo motor de decisão do Hub)
  + PIS/COFINS aplicáveis (docs/pis_cofins_applicability.md)
  + RTC (cClassTrib → CST IBS/CBS) SOMENTE quando o ERP tem a Reforma Tributária ligada (docs/rtc_pis_cofins_model.md)

Campos NOT_APPLICABLE não contam contra a completude. Nenhum campo é exigido só porque a coluna existe.

Onde vive (nenhuma cópia paralela)

Peça Arquivo
regras puras (PIS/COFINS, RTC, evaluate_product) central/app/unified_fiscal_coverage.py
estado do produto (COMPLETE/CORRECTED/BLOCKED_*/BLOCKED_FISCAL_DATA/FAILED_TECHNICAL/NEEDS_REVIEW) central/app/operational_state.py (classify_product_state(..., fiscal=))
leitura do ERP (somente SELECT) agent/src/gti_fiscal_agent/unified_fiscal.py
integração no job do Agent agent/scripts/run_agent_service.py (_unified_fiscal, _fiscal_blocked_products)
snapshot / cobertura no Hub central/app/api.py (_apply_job_outcome — inalterado: usa o mesmo operational)
fila única + fechamento automático central/app/blocked_products.py (resolve_stale_fiscal_blockers)
painel central/app/panel_presentation.py, central/templates/{dashboard,blockers,agent_detail}.html

Estados finais do produto

COMPLETE (+CORRECTED) · SAFE_BLOCKED (BLOCKED_*, incluindo BLOCKED_FISCAL_DATA para PIS/COFINS/RTC) · FAILED_TECHNICAL · NEEDS_REVIEW (não classificado; só incidência PIS/COFINS fora do vocabulário do SGV).

Invariante: TOTAL = COMPLETE + SAFE_BLOCKED + FAILED + UNCLASSIFIED (o Hub calcula "não classificados" como total − completos − bloqueados − falhas, então a igualdade fecha por construção e é reverificada em coverage_invariant_pass). Precedência: um blocker de decisão (NCM, conflito, contexto) permanece o estado principal; blockers fiscais só rebaixam produto que seria completo. Um blocker real vale mais que NEEDS_REVIEW.

Fila única e fechamento

Cada blocker fiscal é um blocker comum: blocker_type=BLOCKED_FISCAL_DATA, field ∈ {PIS, COFINS, RTC}, reason_code = tipo (ex.: PIS_CST_INVALID). A cada job de varredura completa (fiscal_context.evaluated_all=true) o Agent reenvia todos os blockers vigentes e o Hub fecha (AUTO_REEVALUATION) os blockers PIS/COFINS/RTC da instalação não reenviados (dado corrigido, ou RTC desligada). Reprocesso parcial não fecha nada de outros produtos. O fingerprint do blocker inclui os valores fiscais lidos.

Painel

  • Dashboard: um único bloco "Cobertura dos produtos" (Produtos, Completos, Bloqueados com segurança, Falhas técnicas, Não classificados, Cobertura fiscal). Breakdown de blockers: NCM, CEST, CFOP, ST, ICMS, CSOSN, PIS, COFINS, RTC, OTHER (categoria com 0 fica esmaecida).
  • Detalhe do Agent: a mesma cobertura + uma linha discreta "Reforma Tributária: Ativa/Desativada" (do último job). RTC desativada nunca aparece como problema. O bloco "Escopo anterior/ampliado" foi removido.
  • Removidos do código: expanded_scope_summary, expanded_scope_view, LEGACY_SCOPE_COVERAGE, EXPANDED_SCOPE_COVERAGE, UNKNOWN_APPLICABILITY (como estado em massa).

Segurança

Somente leitura. FIREBIRD_WRITES=0: a avaliação abre uma conexão READ COMMITTED READ ONLY, executa apenas SELECT e nunca preenche CCLASSTRIB, PIS ou COFINS. Testes provam que só SELECT é emitido.

Validação no banco real (somente leitura)

scripts/unified_coverage_e2e.py → docs/runs/unified_coverage_e2e*.json. TESTESOFICIAIS (521 produtos, CRT 1):

Antes (só decisão) Depois — RTC desligada (estado do piloto)
Completos 495 (95,01%) 493 (94,63%)
Bloqueados 26 28
Falhas / Não classificados 0 / 0 0 / 0
RTC blockers — 0
PIS / COFINS blockers — 2 / 2 (2 produtos)

Aplicabilidade PIS/COFINS: 518 NOT_APPLICABLE, 2 REQUIRED, 1 OPTIONAL, 0 NEEDS_REVIEW (antes: 492 UNKNOWN_APPLICABILITY). Os 2 produtos bloqueados são legítimos: um com CST 2/2 (formato inválido) e um com incidência SUBST.TRIBUTÁRIA e CST 01 (incompatível com CST 05).

Corpus de clientes (RTC desligada, somente PIS/COFINS; --fiscal-only, sem decisão do Hub)

Banco CRT Produtos NOT_APPLICABLE OPTIONAL Blockers PIS/COFINS Cobertura da parte fiscal
CONSTRUCAO 1 3.712 3.712 0 0 100%
MMMODAS 1 20.997 20.995 1 0 100%
UNIAO 1 8.942 8.170 772 2 produtos (COFINS 000/060, estilo CST de ICMS) 99,98%
RINCAO 3 894 815 79 79 produtos (78 com CST 4 sem zero à esquerda + 1) 91,16%
TESTESOFICIAIS 1 521 518 1 2 produtos 99,62% (94,63% com a decisão do Hub)

OPTIONAL = valor digitado sem flag/incidência especial. RINCAO: 4 deve ser 04 (o seletor do SGV grava 2 dígitos); o motivo do blocker traz a dica UNPADDED_USE_04, nunca aplicada.