64 lines
2.9 KiB
Markdown
64 lines
2.9 KiB
Markdown
# 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.
|