Files
GTI_GERENCIADOR_FISCAL/fiscal/docs/AGENT_COMPANY_CONTEXT_RULES_V1.md
T
gti d21a9d1140 Add 'fiscal/' from commit '102ba84500dbd9655a0471288c3e278652593ca9'
git-subtree-dir: fiscal
git-subtree-mainline: d95165fc8f
git-subtree-split: 102ba84500
2026-09-29 14:43:23 -03:00

3.8 KiB

Agent company context rules V1

Goal: identify ACTIVE_COMPANY, COMPANY_UF and COMPANY_CRT for each Agent installation deterministically and auditably. Read-only; no fiscal rule is created.

What the evidence proved (4 SGV databases, docs/COMPANY_CONTEXT_RESOLUTION_V1.json)

  • Company identity: EMISSOR.EMITENTE_CNPJ equals exactly one C000004.CNPJ in every database, and 100% of the emitted NFC-e access keys (model 65, cUF 29) carry that CNPJ. In RINCAO the other two C000004 rows (SP agro company, refrigeration company) have no emitted documents.
  • Emission authority for CRT/UF/CNPJ = EMISSOR: the emission programs (GtiVendas_NFCe.exe, Envio NF-e.exe) bind QrEmissor.EMITENTE_CRT/EMITENTE_UF/EMITENTE_CNPJ and never reference C000004.CRT or OPTANTE_SIMPLES. The ERP (SGV) binds C000004.CRT (qrFilialCRT, QrSPEDFilialCRT) and OPTANTE_SIMPLES for the filial registry/SPED. The CRT tag inside issued XML could not be read: C000061.NFE_XML and XML_MES.XML store file paths, not content.
  • UF: EMISSOR.EMITENTE_UF, C000004.UF and the cUF of emitted keys agree everywhere (UF_SOURCE_CONFIRMED).
  • CRT: agrees in CONSTRUCAO only. MMMODAS (EMISSOR 1 / C000004 2), RINCAO (3 / 1), UNIAO (1 / 3) are CRT_SOURCE_CONFLICT. OPTANTE_SIMPLES also disagrees with CRT in MMMODAS and UNIAO.

Resolution algorithm (agent/src/gti_fiscal_agent/company_context.py)

  1. Company. Configured COMPANY_CODE/COMPANY_CNPJ must identify exactly one C000004 row. Otherwise: one C000004 row → it; several rows → the single row whose CNPJ equals the single EMISSOR CNPJ; anything else → CONFIG_REQUIRED. First row / lowest code / latest row are never used.
  2. Emitter cross-check. EMISSOR must describe the selected company, else CONFLICT (also covers a configured company that is not the emitter).
  3. Documents. If NFC-e keys exist, some must carry the selected CNPJ (none → CONFLICT); other CNPJs are only a warning (HISTORICAL_NFCE_KEYS_FROM_OTHER_CNPJ, e.g. the test database).
  4. UF. EMISSOR, C000004 and document-key sources must agree; disagreement → CONFLICT, none → UNRESOLVED.
  5. CRT. EMISSOR and C000004 agree → CRT_SOURCE_CONFIRMED. They disagree → CONFLICT unless COMPANY_CRT_SOURCE=EMISSOR|C000004 is configured (resolved, CONFIGURED, confidence MEDIUM, warning recorded). Single source → accepted with warning. None/invalid → UNRESOLVED. Recommendation from the evidence: EMISSOR.
  6. OPTANTE_SIMPLES incoherent with the CRT is reported as a warning, never used to decide.

Preflight

python agent/scripts/preflight_company_context.py [--database <FDB>] prints COMPANY_CONTEXT=PASS|FAIL, company_code, masked CNPJ (first/last 2 digits), UF, CRT, source_of_truth, confidence, warnings, reasons; exit code 2 on FAIL. run_agent_service.py runs it at startup and aborts on FAIL. read_company_context() raises CompanyContextError on FAIL. It fails on: several companies without selection, configured CNPJ/code not found, CRT or UF undeterminable, emitter/selection divergence, unresolved CRT conflict.

Results without configuration

database class reason
CONSTRUCAO AUTO_RESOLVED single row, all sources agree
MMMODAS CONFLICT CRT EMISSOR=1 vs C000004=2
RINCAO CONFLICT company resolved through EMISSOR CNPJ; CRT EMISSOR=3 vs C000004(row)=1
UNIAO CONFLICT CRT EMISSOR=1 vs C000004=3
With COMPANY_CRT_SOURCE=EMISSOR the three resolve (CONFIGURED); a configured non-emitting company or an unknown CNPJ still fails (tested on RINCAO).

Minimal generic Agent requirement

C000004 + C000025; supports_ncm, supports_ipi, supports_cest; a resolvable company context (this preflight PASS); the executor's live column type/length guard. Everything else is capability-based (scripts/sgv_capabilities.py); schema fingerprint equality is NOT required.