Files
sowai-fiscal/README.md
T

64 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# sowai-fiscal
Núcleo fiscal puro da SowAI: motor de regras tributário (imposto-como-dado),
chave de acesso de NF-e (módulo 11) e builder do XML NF-e 55 (leiaute NT
2025.002 v1.40, bindings `nfelib` 2.5.x). Extraído do produto `sowai-auto`
(F1 do plano `sowai-fiscal-svc`) como lib versionada — zero I/O, zero
SQLAlchemy, zero FastAPI, zero acoplamento a nenhum produto: a interface com
o ORM do consumidor é o `Protocol` estrutural `sowai_fiscal.types.TaxRuleLike`.
## Módulos
- `domains` — catálogo `TaxDomain`/`DOMAIN_FIELDS`/`MATCHER_WEIGHTS` +
transposição de CFOP intra→interestadual.
- `chave_acesso` — DV módulo 11, sorteio de `cNF`, montagem da chave de 44
dígitos.
- `tpag` — tabela de códigos `tPag` (MOC, grupo YA02).
- `presets` — presets fiscais seed-editáveis (perfis reais extraídos do
iCode da Thiago Auto Center).
- `resolver``resolve_fiscal`: `FiscalOperation` × regras (`TaxRuleLike`)
`FiscalResult`. Puro, determinístico, fail-closed.
- `xml_builder``build_nfe`: `DadosEmissao` (já resolvido) → objeto `Nfe`
(bindings `nfelib`).
- `types``TaxRuleLike`, o `Protocol` que desacopla o resolver do ORM do
produto.
- `golden_helpers``dados_from_json`/`serialize_infnfe`, usados pelo
corpus golden (`goldens/`) e pelo teste de paridade do produto consumidor.
## Corpus golden
`src/sowai_fiscal/goldens/caso_<nome>.{input.json,expected.xml}` — pares
determinísticos (`dh_emi`/`cnf`/`chave_acesso` pinados no input) que travam
o leiaute XML pré-assinatura gerado a partir de um `DadosEmissao`. São dados
de pacote (lidos via `importlib.resources`), para que o produto consumidor
compare byte a byte contra os MESMOS arquivos da lib instalada — nenhuma
cópia que possa divergir. Regenerar com `uv run python scripts/gen_goldens.py`
apenas quando uma NT mudar o leiaute DE PROPÓSITO.
## Testes
```bash
uv sync
uv run pytest
```
100% local — sem Postgres, sem k8s.
## Versionamento (contrato)
- **SemVer estrito.** Os nomes públicos (`resolve_fiscal`, `build_nfe`,
`montar_chave_acesso`, `TaxDomain`, `DOMAIN_FIELDS`, `MATCHER_WEIGHTS`, `PRESETS`,
`TPAG_CODES`, `DadosEmissao` e sub-dataclasses, `FiscalOperation/FiscalItem/
FiscalResult/TributoLinha`, exceções) são O CONTRATO — mudança incompatível = major.
- **Consumidores pinam por TAG, nunca por branch**: `uv add "sowai-fiscal @
git+https://git.sowai.com.br/jonatan/sowai-fiscal.git@vX.Y.Z"` (o lock pina o hash).
- Goldens mudam SÓ quando uma NT muda o leiaute de propósito (ver seção acima) — e isso
é sempre pelo menos um minor, com nota de release explicando a NT.
## Gap conhecido (registrado na F1, 2026-07-17)
- **Grupo ANP (`gProdANP`) não é emitido** — `ItemData`/builder não têm o campo. NF-e de
óleo lubrificante SEM esse grupo é REJEITADA pela SEFAZ. Fechar na cobertura R1 (junto
do cClassTrib) ANTES de homologar o caso Óleos na F4. O golden `caso_st_intra` cobre
ICMS-ST/CSOSN 500, NÃO cobre ANP.