Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ This allows you to navigate directly to the specific line-window you need instea

| Source Map | File | Lines | Description |
|------------|------|-------|-------------|
| `docs/serializacao_map.md` | `pynfe/processamento/serializacao.py` | 2630 | XML serialization (NF-e, MDF-e, QR codes) |
| `docs/serializacao_map.md` | `pynfe/processamento/serializacao.py` | 2881 | XML serialization (NF-e, MDF-e, QR codes) |
| `docs/comunicacao_map.md` | `pynfe/processamento/comunicacao.py` | 1348 | SEFAZ webservice communication |
| `docs/autorizador_nfse_map.md` | `pynfe/processamento/autorizador_nfse.py` | 538 | NFS-e authorization (Betha/Ginfes) |
| `docs/notafiscal_map.md` | `pynfe/entidades/notafiscal.py` | 1253 | Invoice entities and tax fields |
| `docs/manifesto_map.md` | `pynfe/entidades/manifesto.py` | 447 | MDF-e manifest entities |
| `docs/evento_map.md` | `pynfe/entidades/evento.py` | 237 | Event entities (cancel, correction, etc.) |
| `docs/flags_map.md` | `pynfe/utils/flags.py` | 645 | Constants, namespaces, tax codes |
| `docs/webservices_map.md` | `pynfe/utils/webservices.py` | 572 | SEFAZ endpoint URLs by state |
| `docs/webservices_map.md` | `pynfe/utils/webservices.py` | 684 | SEFAZ endpoint URLs by state |
| `docs/utils_map.md` | `pynfe/utils/__init__.py` | 253 | Utility functions (municipality lookup, signing) |

### How to Use Source Maps
Expand Down Expand Up @@ -113,3 +113,22 @@ ruff format pynfe/
- The `pynfe/data/` directory contains reference data files that should not be modified casually
- Tax code serialization follows strict SEFAZ XML schema ordering — field order matters
- Each Brazilian state has its own SEFAZ endpoint configuration in `webservices.py`
- **A UF's consultation portal host and its authorizer host are different endpoints.** In
`webservices.py`, `HTTPS`/`HOMOLOGACAO` are authorizer host prefixes read only by
`ComunicacaoSefaz._get_url`; `QR_HOST`/`QR_HOST_HOMOLOGACAO` are consultation-portal host
prefixes read only by `qrcode_host` (used for `<qrCode>`/`<urlChave>`). Never make one key
serve both roles: a webservice pointed at the consultation portal gets a redirect plus HTML
instead of a SEFAZ verdict, so emissions fail as transport errors with no rejeicao to explain
them. When a UF changes its consultation host, touch only the `QR_*` keys
- **`<qrCode>` and `<urlChave>` are separate registry entries; each is sourced on its own.**
`urlChave` (consulta por chave de acesso) comes from `CONSULTA_CHAVE`/
`CONSULTA_CHAVE_HOMOLOGACAO` — the COMPLETE, verbatim URL from the official registry
(`URL-ConsultaNFCe_2.00` in ACBr's `ACBrNFeServicos.ini`, cross-checked against ENCAT) —
returned by `url_consulta_chave` with no host prefix ever concatenated onto it. GO rejects
878 when `urlChave` carries the QR Code address, and concatenating a host prefix onto an
already-complete URL is what produced values like `https://nfce.http://www.dfe.ms.gov.br/…`.
Source each field from its own registry entry, never from the sibling field and never from a
sibling UF — a few UFs legitimately register the same address for both, so equality is not by
itself the defect. Per-UF detail and the closed sets of known divergences live in
`docs/webservices_map.md` and `tests/test_nfce_urlchave_por_uf.py`. When a UF's endpoint paths
already embed a subdomain, the authorizer prefix is the scheme alone.
50 changes: 47 additions & 3 deletions docs/reforma_tributaria.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,43 @@ A implementacao cobre:
- `vNF` **NAO inclui** IBS/CBS (proibido em 2025-2026)
- `finNFe=5` (Nota de Debito) e `finNFe=6` (Nota de Credito)
- Campos de entidade para IS (Imposto Seletivo) — **armazenados mas nao serializados** ate o schema suportar (2027)
- Tributacao monofasica (`gIBSCBSMono`) para CST 620 — combustiveis e demais produtos sujeitos ao regime monofasico de IBS/CBS

**Nao inclui** (ainda): Split Payment, cashback, eventos de apuracao assistida, Grupo VB (total do item), Grupo VC (referenciamento de DF-e), Grupo BB (antecipacao de pagamento), tributacao monofasica (`gIBSCBSMono`), diferimento per-item (`gDif`), devolucao de tributos per-item (`gDevTrib`), reducao de aliquota per-item (`gRed`), estorno de credito (`gEstornoCred`), credito presumido per-item (`gCredPresOper`, `gCredPresIBSZFM`).
**Nao inclui** (ainda): Split Payment, cashback, eventos de apuracao assistida, Grupo VB (total do item), Grupo VC (referenciamento de DF-e), Grupo BB (antecipacao de pagamento), diferimento per-item (`gDif`), devolucao de tributos per-item (`gDevTrib`), reducao de aliquota per-item (`gRed`), estorno de credito (`gEstornoCred`), credito presumido per-item (`gCredPresOper`, `gCredPresIBSZFM`).

### Tributacao monofasica — `gIBSCBSMono`

Para produtos com CST 620 (combustiveis, etc.) o grupo emitido dentro de `<IBSCBS>` e `<gIBSCBSMono>` ao inves de `<gIBSCBS>`. Conforme o schema oficial (`DFeTiposBasicos_v1.00.xsd`, type `TMonofasia`), os cinco campos monofasicos vivem sob o wrapper obrigatorio `<gMonoPadrao>` e na ordem definida pelo schema. Alem disso, `<vTotIBSMonoItem>` e `<vTotCBSMonoItem>` sao SIBLINGS de `<gMonoPadrao>` (NAO filhos) e ambos sao OBRIGATORIOS por schema (sem `minOccurs=0`):

```xml
<gIBSCBSMono>
<gMonoPadrao>
<qBCMono>18.0000</qBCMono>
<adRemIBS>0.1000</adRemIBS>
<adRemCBS>0.0000</adRemCBS>
<vIBSMono>1.80</vIBSMono>
<vCBSMono>0.00</vCBSMono>
</gMonoPadrao>
<vTotIBSMonoItem>1.80</vTotIBSMonoItem>
<vTotCBSMonoItem>0.00</vTotCBSMonoItem>
</gIBSCBSMono>
```

| Campo | Tipo | Descricao |
|-------|------|-----------|
| `qBCMono` | TDec1104RTC | Quantidade tributada na base monofasica |
| `adRemIBS` | TDec_0302_04RTC | Aliquota ad rem IBS (valor em BRL por unidade) |
| `adRemCBS` | TDec_0302_04RTC | Aliquota ad rem CBS (valor em BRL por unidade) |
| `vIBSMono` | TDec1302RTC | Valor IBS monofasico |
| `vCBSMono` | TDec1302RTC | Valor CBS monofasico |
| `vTotIBSMonoItem` | TDec1302RTC | Total IBS monofasico do item (sibling de `gMonoPadrao`) |
| `vTotCBSMonoItem` | TDec1302RTC | Total CBS monofasico do item (sibling de `gMonoPadrao`) |

Atributos na entidade `NotaFiscalProduto`: `ibscbs_q_bc_mono`, `ibscbs_ad_rem_ibs`, `ibscbs_v_ibs_mono`, `ibscbs_ad_rem_cbs`, `ibscbs_v_cbs_mono`, `ibscbs_v_tot_ibs_mono_item`, `ibscbs_v_tot_cbs_mono_item`.

Para itens single-line (sem retencao / retencao anterior / diferimento), `vTotIBSMonoItem == vIBSMono` e `vTotCBSMonoItem == vCBSMono`. Quando os atributos nao sao informados pelo caller, o serializador emite `0.00` (default seguro durante o Teste de Carga 2026 com ad rem zerados).

Durante o Teste de Carga 2026 os ad rem ainda nao foram publicados pela SEFAZ, entao os valores podem ser zerados — o grupo `gIBSCBSMono` ainda sera emitido corretamente.

## CSTs disponiveis

Expand Down Expand Up @@ -300,13 +335,22 @@ Os totais ficam em um grupo **separado** de `<ICMSTot>`, como irmao dentro de `<
<vCredPres>0.00</vCredPres>
<vCredPresCondSus>0.00</vCredPresCondSus>
</gCBS>
<!-- gMono: totais monofasia (nao implementado) -->
<gMono> <!-- Totais monofasia (DEV-1955) -->
<vIBSMono>0.00</vIBSMono> <!-- Total IBS monofasico padrao -->
<vCBSMono>0.00</vCBSMono> <!-- Total CBS monofasica padrao -->
<vIBSMonoReten>0.00</vIBSMonoReten> <!-- Total IBS monofasico sujeito a retencao -->
<vCBSMonoReten>0.00</vCBSMonoReten> <!-- Total CBS monofasica sujeita a retencao -->
<vIBSMonoRet>0.00</vIBSMonoRet> <!-- Total IBS monofasico retido anteriormente -->
<vCBSMonoRet>0.00</vCBSMonoRet> <!-- Total CBS monofasica retida anteriormente -->
</gMono>
<!-- gEstornoCred: totais estorno de credito (nao implementado) -->
</IBSCBSTot>
</total>
```

> Os subgrupos `gIBS` e `gCBS` sao opcionais (`minOccurs="0"`) — emitidos apenas quando ha valores. Os campos `vDif`, `vDevTrib`, `vCredPres` e `vCredPresCondSus` sao obrigatorios dentro de cada subgrupo (emitidos como "0.00" quando nao utilizados).
>
> O subgrupo `gMono` e opcional, mas obrigatorio sempre que algum item da NF-e carregar `<gIBSCBSMono>` (CST 620, etc.). Quando emitido, **todos os seis filhos** sao obrigatorios (`vIBSMono`, `vCBSMono`, `vIBSMonoReten`, `vCBSMonoReten`, `vIBSMonoRet`, `vCBSMonoRet`). Omitir `<gMono>` em uma NF-e com items monofasicos faz a SEFAZ rejeitar com `cStat 1119 - "Total de IBS e CBS nao informado"`. Os totais `Reten`/`Ret` ainda nao sao acumulados a nivel de item (PyNFe ainda so emite `<gMonoPadrao>`), entao serao "0.00" ate que `<gMonoReten>` / `<gMonoRet>` / `<gMonoDif>` sejam suportados a nivel de item.

### Cabecalho — `cMunFGIBS` no `<ide>`

Expand Down Expand Up @@ -338,7 +382,7 @@ Esses CSTs geram apenas `<CST>` e `<cClassTrib>`, sem `<gIBSCBS>`.

- **`cClassTrib`**: Emitido quando informado (campo obrigatorio na pratica)
- **`cMunFGIBS`**: Emitido no `<ide>` apenas quando informado
- **`<IBSCBSTot>`**: Tipo `TIBSCBSMonoTot`. Omitido se todos os totais forem zero. Quando emitido, `vBCIBSCBS` e obrigatorio como primeiro filho; `gIBS` e `gCBS` sao opcionais
- **`<IBSCBSTot>`**: Tipo `TIBSCBSMonoTot`. Omitido se todos os totais forem zero E nenhum item carregar `<gIBSCBSMono>`. Quando emitido, `vBCIBSCBS` e obrigatorio como primeiro filho; `gIBS`, `gCBS` e `gMono` sao opcionais (mas `gMono` e obrigatorio sempre que houver items monofasicos)
- **`<IBSCBS>`**: Tipo `TTribNFe`. Omitido completamente se `ibscbs_cst` nao for informado
- **IS (`<IS>`)**: Tipo `TIS`. **Nao emitido no XML** — serializacao desabilitada ate 2027
- **`<ISTot>`**: Tipo `TISTot`. **Nao emitido** — sera irmao de `<IBSCBSTot>` (antes dele no schema)
Expand Down
30 changes: 16 additions & 14 deletions docs/serializacao_map.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
# Source Map: `serializacao.py` (2771 lines)
# Source Map: `serializacao.py` (2881 lines)

XML serialization of NF-e, NFC-e, NFS-e and MDF-e documents into SEFAZ-compliant XML format.

## Classes Overview

| Class | Lines | Purpose |
|-------|-------|---------|
| `Serializacao` | 30-63 | Abstract base class (not instantiable directly) |
| `SerializacaoXML` | 66-1860 | Main NF-e/NFC-e XML serialization |
| `SerializacaoQrcode` | 2102-2206 | NFC-e QR Code generation |
| `SerializacaoNfse` | 2209-2275 | NFS-e serialization (Betha/Ginfes) |
| `SerializacaoQrcodeMDFe` | 2278-2301 | MDF-e QR Code generation |
| `SerializacaoMDFe` | 2304-2771 | MDF-e XML serialization |
| `Serializacao` | 31-65 | Abstract base class (not instantiable directly) |
| `SerializacaoXML` | 67-2222 | Main NF-e/NFC-e XML serialization |
| `SerializacaoQrcode` | 2225-2309 | NFC-e QR Code generation |
| `SerializacaoNfse` | 2312-2378 | NFS-e serialization (Betha/Ginfes) |
| `SerializacaoQrcodeMDFe` | 2381-2404 | MDF-e QR Code generation |
| `SerializacaoMDFe` | 2407-2881 | MDF-e XML serialization |

---

## `Serializacao` (base class) — Lines 30-63
## `Serializacao` (base class) — Lines 31-65

Abstract base for all serializers. Stores `_fonte_dados`, `_ambiente` (1=prod, 2=homolog), `_contingencia`, `_so_cpf`.

## `SerializacaoXML` — Lines 66-1860
## `SerializacaoXML` — Lines 67-2222

### Exported Methods
| Method | Lines | Purpose |
Expand Down Expand Up @@ -102,19 +102,21 @@ Abstract base for all serializers. Stores `_fonte_dados`, `_ambiente` (1=prod, 2

---

## `SerializacaoQrcode` — Lines 2102-2206
## `SerializacaoQrcode` — Lines 2225-2309

Generates NFC-e QR Code URL. Handles online/offline modes and state-specific URL patterns (SP, BA, MG, etc.).
Generates the `<infNFeSupl>` block. `<qrCode>` handles online/offline modes and the
state-specific host/path patterns; `<urlChave>` is a separate registry and comes straight from
`webservices.url_consulta_chave` — never concatenate a host onto it (DEV-2468, rejeicao 878).

## `SerializacaoNfse` — Lines 2209-2275
## `SerializacaoNfse` — Lines 2312-2378

Delegates to Betha or Ginfes serializers. Methods: `gerar`, `gerar_lote`, `consultar_nfse`, `consultar_lote`, `consultar_rps`, `consultar_situacao_lote`, `cancelar`.

## `SerializacaoQrcodeMDFe` — Lines 2278-2301
## `SerializacaoQrcodeMDFe` — Lines 2381-2404

Generates MDF-e QR Code URL using SVRS endpoint.

## `SerializacaoMDFe` — Lines 2304-2771
## `SerializacaoMDFe` — Lines 2407-2881

### Methods
| Method | Lines | Purpose |
Expand Down
92 changes: 61 additions & 31 deletions docs/webservices_map.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
# Source Map: `webservices.py` (572 lines)
# Source Map: `webservices.py` (684 lines)

SEFAZ webservice endpoint URLs organized by document type, state, and environment.

## Sections

| Section | Lines | Variable | Purpose |
|---------|-------|----------|---------|
| NFC-e endpoints | 8-295 | `NFCE` | NFC-e webservice URLs and QR Code URLs by state |
| NF-e endpoints | 297-471 | `NFE` | NF-e webservice URLs by state |
| NFS-e endpoints | 473-499 | `NFSE` | NFS-e URLs (Betha, Ginfes) |
| MDF-e endpoints | 501-516 | `MDFE` | MDF-e URLs (SVRS only) |
| CT-e endpoints | 518-572 | `CTE` | CT-e URLs by state |
| Host roles + `qrCode` vs `urlChave` | 1-44 | — | Module docstring: which key family each consumer may read |
| NFC-e endpoints | 49-363 | `NFCE` | NFC-e webservice URLs, QR Code URLs and consultation URLs by state |
| `qrcode_host` helper | 366-384 | — | Consultation-portal host prefix for `<qrCode>` |
| `url_consulta_chave` helper | 392-406 | — | Complete `<urlChave>` URL, never concatenated |
| NF-e endpoints | 412-583 | `NFE` | NF-e webservice URLs by state |
| NFS-e endpoints | 586-611 | `NFSE` | NFS-e URLs (Betha, Ginfes) |
| MDF-e endpoints | 614-628 | `MDFE` | MDF-e URLs (SVRS only) |
| CT-e endpoints | 630-684 | `CTE` | CT-e URLs by state |

## URL Structure

Expand All @@ -22,42 +25,69 @@ Each state/virtual environment entry contains:
- `INUTILIZACAO` — Number invalidation endpoint
- `EVENTOS` — Event reception endpoint
- `CADASTRO` — Registration query endpoint (some states)
- `HTTPS` — Production base URL prefix
- `HOMOLOGACAO` — Homologation base URL prefix
- `QR` — QR Code URL (NFC-e only)
- `URL` — Consultation URL (NFC-e only)
- `HTTPS` — Production base URL prefix of the AUTHORIZER (webservices; read only by
`ComunicacaoSefaz._get_url`)
- `HOMOLOGACAO` — Homologation base URL prefix of the AUTHORIZER
- `QR_HOST` / `QR_HOST_HOMOLOGACAO` — Base URL prefix of the CONSULTATION portal, used for
`<qrCode>`/`<urlChave>` (read only by `qrcode_host`); falls back to `HTTPS`/`HOMOLOGACAO`
for UFs that serve both roles from the same host
- `QR` — QR Code path (NFC-e only; `QR_HOMOLOGACAO` where the path differs per environment)
- `URL` — Legacy consultation path (NFC-e only), still read by `url_consulta_chave` as a
fallback for UFs that declare no `CONSULTA_CHAVE`
- `CONSULTA_CHAVE` / `CONSULTA_CHAVE_HOMOLOGACAO` — COMPLETE, verbatim `<urlChave>` from the
official registry (`URL-ConsultaNFCe_2.00` in ACBr / the ENCAT listing). Returned as-is: no
host prefix is ever concatenated onto it. Declare this for any UF you add or fix

The two host families must never be shared: a UF such as GO answers webservice POSTs sent to
its consultation host with a load-balancer redirect and HTML, so the invoice never receives a
SEFAZ verdict and the failure surfaces as a transport/XML-parse error, not a rejeicao.

`<qrCode>` and `<urlChave>` are likewise separate registries, each with its own entry in the
official listing, so one is never a safe substitute for the other: GO rejects 878 when
`urlChave` carries the QR Code address. Equality is not by itself the defect — the registry
does list the same address for both fields in a few UFs (SC today) — so always compare against
the registry entry for the field you are changing, never against the sibling field. `urlChave`
values live in `CONSULTA_CHAVE*`; `qrCode` is built from `QR*` over `qrcode_host`. The exact set
of UFs where the two addresses coincide is pinned in `tests/test_nfce_urlchave_por_uf.py`.

## State/Virtual Environment Groups

### NFC-e (`NFCE`) — Lines 8-295
### NFC-e (`NFCE`) — Lines 49-363
| Key | Lines | Description |
|-----|-------|-------------|
| Individual states | 9-278 | RO, AC, AM, RR, PA, AP, TO, MA, PI, CE, RN, PB, PE, AL, SE, BA, MG, ES, RJ, SP, PR, SC, RS, MS, MT, GO, DF |
| `SVRS` | 284-294 | Virtual SEFAZ RS (fallback for states without own NFC-e) |
| Individual states | 50-350 | RO, AC, AM, RR, PA, AP, TO, MA, PI, CE, RN, PB, PE, AL, SE, BA, MG, ES, RJ, SP, PR, SC, RS, MS, MT, GO, DF |
| `SVRS` | 352-362 | Virtual SEFAZ RS (fallback for states without own NFC-e) |

### NF-e (`NFE`) — Lines 297-471
### NF-e (`NFE`) — Lines 412-583
| Key | Lines | Description |
|-----|-------|-------------|
| `AN` | 302-309 | National environment (events, distribution) |
| Individual states | 310-428 | AM, MA, PE, BA, MG, SP, PR, RS, MS, MT, GO |
| `SVAN` | 430-440 | Virtual SEFAZ AN (MA for NF-e) |
| `SVRS` | 441-451 | Virtual SEFAZ RS (most states) |
| `SVC-AN` | 452-460 | Contingency AN |
| `SVC-RS` | 461-470 | Contingency RS |

### NFS-e (`NFSE`) — Lines 473-499
| `AN` | 414-421 | National environment (events, distribution) |
| Individual states | 422-541 | AM, MA, PE, BA, MG, SP, PR, RS, MS, MT, GO |
| `SVAN` | 542-552 | Virtual SEFAZ AN (MA for NF-e) |
| `SVRS` | 553-563 | Virtual SEFAZ RS (most states) |
| `SVC-AN` | 564-572 | Contingency AN |
| `SVC-RS` | 573-582 | Contingency RS |

### NFS-e (`NFSE`) — Lines 586-611
| Key | Lines | Description |
|-----|-------|-------------|
| `BETHA` | 476-486 | Betha provider (HTTP WSDL) |
| `GINFES` | 488-498 | Ginfes provider (HTTPS WSDL) |
| `BETHA` | 588-598 | Betha provider (HTTP WSDL) |
| `GINFES` | 600-610 | Ginfes provider (HTTPS WSDL) |

### MDF-e (`MDFE`) — Lines 501-516
Only `SVRS` — single authorizer for all states.
### MDF-e (`MDFE`) — Lines 614-628
Only `SVRS` (616-627) — single authorizer for all states.

### CT-e (`CTE`) — Lines 518-572
### CT-e (`CTE`) — Lines 630-684
| Key | Lines | Description |
|-----|-------|-------------|
| `AN` | 519-523 | National environment (distribution) |
| Individual states | 524-558 | MT, MS, MG, PR, RS, SP |
| `SVRS` | 560-565 | Virtual SEFAZ RS |
| `SVSP` | 566-571 | Virtual SEFAZ SP (AP, PE, RR) |
| `AN` | 631-635 | National environment (distribution) |
| Individual states | 636-671 | MT, MS, MG, PR, RS, SP |
| `SVRS` | 672-677 | Virtual SEFAZ RS |
| `SVSP` | 678-683 | Virtual SEFAZ SP (AP, PE, RR) |

## Helpers

| Function | Lines | Purpose |
|----------|-------|---------|
| `qrcode_host(uf, producao=True)` | 366-384 | Consultation-portal host prefix for `<qrCode>`, with fallback to the webservice host |
| `url_consulta_chave(uf, producao=True)` | 392-406 | Complete `<urlChave>` URL from `CONSULTA_CHAVE*`, falling back to the legacy `URL` path (which it prefixes with `qrcode_host`) |
Loading
Loading