@useinvio/nfse-sdk 2.2.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/JSON_MAPPING.md +30 -17
- package/README.md +33 -14
- package/dist/certificateValidation.d.ts +3 -1
- package/dist/certificateValidation.js +7 -2
- package/dist/certificateValidation.js.map +1 -1
- package/dist/client.d.ts +4 -1
- package/dist/client.js +3 -3
- package/dist/client.js.map +1 -1
- package/dist/decimal.d.ts +7 -0
- package/dist/decimal.js +24 -0
- package/dist/decimal.js.map +1 -0
- package/dist/dpsJson.js +15 -45
- package/dist/dpsJson.js.map +1 -1
- package/dist/dpsNormalization.d.ts +10 -0
- package/dist/dpsNormalization.js +85 -0
- package/dist/dpsNormalization.js.map +1 -0
- package/dist/emissaoNota.js +25 -7
- package/dist/emissaoNota.js.map +1 -1
- package/dist/fiscalValidation.d.ts +1 -0
- package/dist/fiscalValidation.js +108 -45
- package/dist/fiscalValidation.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/xmlInspection.d.ts +6 -0
- package/dist/xmlInspection.js +61 -0
- package/dist/xmlInspection.js.map +1 -0
- package/docs/CORRECOES_EMISSAO.md +55 -0
- package/docs/FISCAL_MATRIX.md +11 -0
- package/docs/REGRAS_NEGOCIO_EMISSAO.md +317 -0
- package/examples/README.md +3 -0
- package/examples/client-resource.ts +5 -39
- package/examples/emit-homologation.ts +3 -38
- package/examples/generate-dps-xml.ts +3 -40
- package/examples/handle-errors.ts +3 -2
- package/examples/payloads.ts +36 -0
- package/llms.txt +7 -2
- package/package.json +1 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { DOMParser } from '@xmldom/xmldom';
|
|
2
|
+
import { execFileSync } from 'node:child_process';
|
|
3
|
+
import { XmllintUnavailableError } from './xsdValidation.js';
|
|
4
|
+
const NS = 'http://www.sped.fazenda.gov.br/nfse';
|
|
5
|
+
export function parseNfseXml(xml, rootName) {
|
|
6
|
+
const errors = [];
|
|
7
|
+
const doc = new DOMParser({ errorHandler: (level, message) => errors.push(`${level}: ${message}`) }).parseFromString(xml, 'application/xml');
|
|
8
|
+
const roots = Array.from(doc.childNodes).filter((node) => node.nodeType === 1);
|
|
9
|
+
const strayText = Array.from(doc.childNodes).some((node) => node.nodeType === 3 && node.textContent?.trim());
|
|
10
|
+
const root = doc.documentElement;
|
|
11
|
+
if (errors.length || doc.doctype || strayText || roots.length !== 1 || root?.localName !== rootName || root.namespaceURI !== NS) {
|
|
12
|
+
throw new Error(`XML ${rootName} invalido: documento malformado, raiz ou namespace inesperado.`);
|
|
13
|
+
}
|
|
14
|
+
// xmldom recovers silently from some malformed XML (e.g. unescaped '&').
|
|
15
|
+
// Use the existing XML runtime for strict syntax checking, without fetching DTDs.
|
|
16
|
+
try {
|
|
17
|
+
execFileSync('xmllint', ['--noout', '--nonet', '-'], {
|
|
18
|
+
input: xml, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'],
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
const failure = error;
|
|
23
|
+
if (failure.status === 1)
|
|
24
|
+
throw new Error(`XML ${rootName} invalido: documento malformado.`);
|
|
25
|
+
throw new XmllintUnavailableError(`Falha ao verificar XML ${rootName} com xmllint (${failure.code ?? failure.status ?? 'desconhecida'}).`, error);
|
|
26
|
+
}
|
|
27
|
+
return root;
|
|
28
|
+
}
|
|
29
|
+
export function directChildren(element, name) {
|
|
30
|
+
return Array.from(element.childNodes).filter((node) => node.nodeType === 1 && node.localName === name && node.namespaceURI === NS);
|
|
31
|
+
}
|
|
32
|
+
export function dpsEnvironment(xml) {
|
|
33
|
+
const root = parseNfseXml(xml, 'DPS');
|
|
34
|
+
const info = directChildren(root, 'infDPS');
|
|
35
|
+
const fields = info.length === 1 ? directChildren(info[0], 'tpAmb') : [];
|
|
36
|
+
const value = fields.length === 1 ? fields[0].textContent : undefined;
|
|
37
|
+
if (value !== '1' && value !== '2')
|
|
38
|
+
throw new Error('XML da DPS deve informar um unico tpAmb valido (1 ou 2).');
|
|
39
|
+
return value === '1' ? 'producao' : 'restrita';
|
|
40
|
+
}
|
|
41
|
+
export function assertEnvironment(actual, expected) {
|
|
42
|
+
if (actual !== expected)
|
|
43
|
+
throw new Error('Ambiente do XML da DPS difere do ambiente de transmissao.');
|
|
44
|
+
}
|
|
45
|
+
export function authorizedAccessKey(xml, body) {
|
|
46
|
+
const root = parseNfseXml(xml, 'NFSe');
|
|
47
|
+
const info = directChildren(root, 'infNFSe');
|
|
48
|
+
if (info.length > 1)
|
|
49
|
+
throw new Error('Resposta contem multiplos elementos infNFSe.');
|
|
50
|
+
const id = info[0]?.getAttribute('Id') || undefined;
|
|
51
|
+
if (id !== undefined && !/^NFS\d{50}$/.test(id))
|
|
52
|
+
throw new Error('Identificador da NFS-e invalido.');
|
|
53
|
+
const candidates = [body.chaveAcesso, body.ChaveAcesso, id?.slice(3)].filter((value) => value !== undefined);
|
|
54
|
+
if (!candidates.length || candidates.some((value) => typeof value !== 'string' || !/^\d{50}$/.test(value))) {
|
|
55
|
+
throw new Error('Resposta de autorizacao sem chave de acesso valida de 50 digitos.');
|
|
56
|
+
}
|
|
57
|
+
if (new Set(candidates).size !== 1)
|
|
58
|
+
throw new Error('Chaves de acesso divergentes no corpo e/ou XML da resposta.');
|
|
59
|
+
return candidates[0];
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=xmlInspection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xmlInspection.js","sourceRoot":"","sources":["../xmlInspection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Migracao 2.x → 3.0.0 — 06/10/2026
|
|
2
|
+
|
|
3
|
+
Este e o guia de migracao da versao 3.0.0. O diagnostico historico em [REGRAS_NEGOCIO_EMISSAO.md](REGRAS_NEGOCIO_EMISSAO.md) permanece preservado. O leiaute local continua DPS 1.01; nao houve atualizacao dos XSD nem mudanca do enquadramento fiscal suportado.
|
|
4
|
+
|
|
5
|
+
## Breaking changes
|
|
6
|
+
|
|
7
|
+
Atualize a integracao se ela dependia de qualquer comportamento abaixo:
|
|
8
|
+
|
|
9
|
+
| Antes (2.x) | Agora (3.0.0) | Acao |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| Campos opcionais vazios, `null` ou tipos incorretos podiam chegar ao builder/XSD. | Sao rejeitados com `INVALID_STRUCTURE` ou erro de validacao. | Omita o campo ou informe um valor valido. |
|
|
12
|
+
| Valores pequenos podiam virar `0.00` no XML; limites eram deixados ao XSD. | Valores de servico que arredondam para zero e valores fora dos limites locais sao rejeitados antes do XML. | Ajuste o valor e a escala antes de chamar o SDK. |
|
|
13
|
+
| `obra` podia ser incompleta e `inscImobFisc` era serializada depois de `cObra`. | `cObra` e obrigatorio quando houver obra; a ordem segue o XSD. | Informe `cObra` e teste a integracao contra 3.0.0. |
|
|
14
|
+
| XML externo podia usar um ambiente diferente do destino. | `tpAmb` e obrigatorio e deve coincidir com o ambiente de transmissao. | Corrija o XML ou remova a opcao de ambiente conflitante. |
|
|
15
|
+
| Certificado expirado podia chegar a assinatura/transmissao. | A vigencia e obrigatoria antes de assinar e antes de enviar. | Renove o certificado e trate `CertificateValidationError`. |
|
|
16
|
+
| HTTP 2xx sem resposta autorizada completa podia retornar chave vazia. | Gera `EmitirNotaError` com `INVALID_AUTHORIZATION_RESPONSE`. | Concilie a DPS antes de reenviar. |
|
|
17
|
+
| Intermediario com NIF/`cNaoNIF` podia passar pela pre-validacao e ser perdido no XML. | E rejeitado. | Use CPF/CNPJ ou envie XML externo completo. |
|
|
18
|
+
|
|
19
|
+
Nao sao breaking changes: divergencias cambiais agora produzem `warnings`, sem impedir emissao; `invoices.get(chave, { ambiente })` recebe apenas um segundo argumento opcional; `assertCertificateValidity` e uma nova exportacao.
|
|
20
|
+
|
|
21
|
+
## Mudancas de comportamento
|
|
22
|
+
|
|
23
|
+
| Area | Comportamento corrigido |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| Valores e atalhos | Resolucao por campo compartilhada pelo builder e validador; `valores` prevalece sobre atalhos. `comercioExterior` prevalece integralmente sobre `comExt`. |
|
|
26
|
+
| Relatorio | `normalizedPayload` e uma copia independente. `issues` contem erros; `warnings` contem avisos. Entradas com blocos/tipos incorretos retornam `INVALID_STRUCTURE`. |
|
|
27
|
+
| Cambio | `CURRENCY_BRL_MISMATCH` e `CURRENCY_FOREIGN_MISMATCH` avisam sobre divergencias em centavos sem bloquear nem substituir valores explicitos. |
|
|
28
|
+
| Precisao | Multiplicacao decimal exata com entradas originais; todos os valores monetarios serializados com duas casas, inclusive `comExt.vServMoeda`. Arredondamento metade para cima. |
|
|
29
|
+
| Limites | Valores de servico que arredondam para zero ou ultrapassam o tamanho do XSD sao rejeitados. Retencoes federais e aliquotas tambem passam pela validacao antecipada. |
|
|
30
|
+
| Estrutura | Opcionais vazios/nulos e tipos incorretos sao rejeitados. Datas de calendario, horarios, offsets e dominios pequenos de comercio exterior seguem os tipos locais. |
|
|
31
|
+
| Obra | `cObra` obrigatorio no modelo suportado; `inscImobFisc` opcional vem antes de `cObra` no XML. Ambos limitados a 30 caracteres. |
|
|
32
|
+
| Intermediario | NIF/`cNaoNIF` rejeitados, pois o builder atual so transmite CPF/CNPJ. |
|
|
33
|
+
| Ambiente JSON | Resolvido antes do XML: opcoes → request → restrita. XML e destino usam o mesmo ambiente. |
|
|
34
|
+
| Ambiente XML | Derivado de `tpAmb`; conflitos explicitos e divergencias na nota preparada bloqueiam o envio. |
|
|
35
|
+
| Consulta | `invoices.get(chave, { ambiente })` permite sobrescrita; padrao usa `defaults.ambiente` ou construtor, sem lembrar a ultima emissao. |
|
|
36
|
+
| Certificado | Vigencia obrigatoria antes da assinatura e novamente antes do envio. Titularidade permanece uma chamada explicita. |
|
|
37
|
+
| Autorizacao | Exige descompactacao, XML bem formado com raiz/namespace NFSe e chave de 50 digitos. Chaves do corpo e XML, quando presentes, devem ser validas e iguais. |
|
|
38
|
+
|
|
39
|
+
`assertCertificateValidity(pfx, now?)` e `GetInvoiceOptions` foram adicionados aos exports publicos. As assinaturas existentes continuam disponiveis; o segundo argumento de `invoices.get` e opcional. Certificados fora da vigencia produzem os codigos existentes `CERTIFICATE_NOT_YET_VALID`/`CERTIFICATE_EXPIRED`.
|
|
40
|
+
|
|
41
|
+
As novas rejeicoes tecnicas podem exigir ajustes de integracoes que enviavam campos vazios, datas fora do formato, obra incompleta ou valores fora dos limites. Divergencias cambiais continuam aceitas. O SDK nao recupera precisao que ja tenha sido perdida no `number` da cotacao.
|
|
42
|
+
|
|
43
|
+
## Respostas e infraestrutura
|
|
44
|
+
|
|
45
|
+
HTTP 2xx incompleto ou inconsistente gera `EmitirNotaError` com `INVALID_AUTHORIZATION_RESPONSE`, preservando status, corpo e identificador da DPS. Isso nao prova rejeicao fiscal: a aplicacao deve conciliar antes de reenviar. Rejeicoes oficiais preservam codigo, descricao e complemento. Falhas de transporte continuam propagadas, sem retentativas.
|
|
46
|
+
|
|
47
|
+
O `xmllint`, ja necessario para XSD, tambem verifica a sintaxe XML antes da leitura de ambiente e da aceitacao de respostas; o parser DOM sozinho recupera silenciosamente alguns XMLs malformados. DTDs nao sao aceitos, e a verificacao usa `--nonet`. Falha do executavel continua sendo `XmllintUnavailableError`, distinguida de resposta fiscal invalida. Nao se valida a assinatura nem o XSD completo da NFS-e recebida.
|
|
48
|
+
|
|
49
|
+
## Cobertura e limites
|
|
50
|
+
|
|
51
|
+
Os testes usam `node:test`, certificados sinteticos e `https.request` simulado, sem acesso a SEFIN. Cobrem regimes, documentos, normalizacao, conversao, precedencias, limites, datas, obra, tributos federais, vigencia, ambiente, respostas e erros. Os payloads de [examples/payloads.ts](../examples/payloads.ts) e os exemplos de emissao de README/ENGLISH sao validados contra o XSD.
|
|
52
|
+
|
|
53
|
+
Permanecem as restricoes anteriores de nacional/exportacao e `totTrib` por regime, inclusive as limitacoes conhecidas de pais do resultado e dependencias de retencao. IBS/CBS, descontos, deducoes, prestacao por pais, representacao, conciliacao automatica e novos cenarios fiscais nao foram implementados. Nenhuma nota real foi transmitida e nenhum pacote foi publicado.
|
|
54
|
+
|
|
55
|
+
Validacao de manutencao: `npm run typecheck`, `npm test` (inclui build) e `npm pack --dry-run`.
|
package/docs/FISCAL_MATRIX.md
CHANGED
|
@@ -10,3 +10,14 @@ O SDK valida estas combinações antes de construir, assinar ou transmitir a DPS
|
|
|
10
10
|
| ME/EPP (`opSimpNac=3`) | Somente `pTotTribSN` | `indTotTrib` e percentuais federal/estadual/municipal |
|
|
11
11
|
|
|
12
12
|
O SDK usa os XSDs NFS-e Nacional v1.01 distribuídos no pacote para validar a estrutura. A matriz não substitui a verificação contábil nem uma homologação no ambiente restrito da SEFIN.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## Resolucao e validacao tecnica
|
|
16
|
+
|
|
17
|
+
- A matriz usa a mesma resolucao por campo do builder: `valores` prevalece sobre os atalhos legados. `comercioExterior` prevalece integralmente sobre `comExt`.
|
|
18
|
+
- Divergencias cambiais sao avisos em `warnings`; valores explicitos continuam prevalecendo. Somente erros em `issues` bloqueiam a geracao.
|
|
19
|
+
- A carga por regime e a classificacao nacional/exterior acima permanecem inalteradas. Nao foram adicionadas dependencias fiscais de retencao ou proibicao de pais `BR` na exportacao.
|
|
20
|
+
- Valores de servico devem continuar positivos depois do arredondamento; codigos e limites numericos seguem os XSD locais. Campos opcionais vazios ou nulos sao invalidos.
|
|
21
|
+
- Intermediario estrangeiro, IBS/CBS, descontos, deducoes e prestacao por pais continuam fora do modelo suportado.
|
|
22
|
+
|
|
23
|
+
Veja [CORRECOES_EMISSAO.md](CORRECOES_EMISSAO.md) para ambiente, certificados, respostas e compatibilidade. [REGRAS_NEGOCIO_EMISSAO.md](REGRAS_NEGOCIO_EMISSAO.md) permanece o diagnostico historico anterior a essas correcoes.
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# Regras de negócio da emissão de NFS-e — cenário atual
|
|
2
|
+
|
|
3
|
+
**Data da análise:** 06/10/2026 · **Produto:** `@useinvio/nfse-sdk` 2.2.0 · **Código:** commit `0bfbefa` · **Leiaute local:** DPS 1.01.
|
|
4
|
+
|
|
5
|
+
Este relatório descreve o comportamento implementado no repositório: emissão nacional, emissão para o exterior, validações, exceções e limitações. A cobertura se refere às decisões existentes no SDK; não representa um catálogo de todas as legislações municipais. Aplicações consumidoras, cadastros de clientes e configurações de produção não estão neste repositório.
|
|
6
|
+
|
|
7
|
+
**Leitura das regras:** “aceito” significa que a entrada passa pela etapa indicada; somente a resposta da SEFIN confirma a autorização. Regras do SDK, restrições do XSD e enquadramento tributário são camadas distintas.
|
|
8
|
+
|
|
9
|
+
## 1. Visão do produto
|
|
10
|
+
|
|
11
|
+
O SDK recebe uma declaração de prestação de serviços (DPS), gera o XML, valida sua estrutura, assina com certificado digital e transmite à SEFIN Nacional. A SEFIN devolve a NFS-e autorizada ou uma rejeição.
|
|
12
|
+
|
|
13
|
+
A aplicação informa o enquadramento tributário. O SDK não determina o município de incidência, não escolhe CST ou alíquotas, não calcula os tributos nem consulta a situação cadastral do contribuinte. Seus cálculos se limitam à conversão cambial e ao arredondamento dos valores declarados.
|
|
14
|
+
|
|
15
|
+
Há duas categorias operacionais no JSON:
|
|
16
|
+
|
|
17
|
+
| Categoria | Como o sistema identifica | Consequência |
|
|
18
|
+
| --- | --- | --- |
|
|
19
|
+
| Nacional | Ausência de `emissao.comercioExterior` e `emissao.comExt` | Exige valor em reais; restringe o tomador a CPF/CNPJ e endereço nacional. |
|
|
20
|
+
| Exterior, tratado como exportação | Presença de um desses blocos, inclusive objeto vazio | Exige moeda, cotação, país do resultado e, por combinação das validações, `tribISSQN="3"`. |
|
|
21
|
+
|
|
22
|
+
**Principal limite de produto:** cliente estrangeiro, local da prestação, local do resultado e tratamento do ISSQN não são decisões independentes na implementação atual. A presença do bloco de comércio exterior determina o enquadramento operacional de exportação.
|
|
23
|
+
|
|
24
|
+
Para o ISS, a LC 116/2003 distingue exportação de serviço de serviço desenvolvido no Brasil cujo resultado aqui se verifica, ainda que pago por residente no exterior. Também prevê incidência sobre serviços provenientes do exterior. Logo, identificar um cliente estrangeiro não basta para concluir o enquadramento fiscal; o SDK não realiza essa análise. [Fonte: LC 116/2003, arts. 1º e 2º](https://www.planalto.gov.br/ccivil_03/leis/lcp/lcp116.htm).
|
|
25
|
+
|
|
26
|
+
## 2. Caminho da emissão e responsabilidades
|
|
27
|
+
|
|
28
|
+
| Etapa | Comportamento atual | Responsável |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| Preparar dados | Definir prestador, serviço, tomador, natureza tributária, retenções, valores, série e número | Aplicação consumidora |
|
|
31
|
+
| Montar JSON | `NfseClient.invoices.buildDpsJson` combina padrões e dados da chamada; não executa a validação fiscal completa | SDK |
|
|
32
|
+
| Validar JSON | `validateDpsJsonRequest` reúne problemas; `buildDpsFromJson` bloqueia entradas inválidas | SDK |
|
|
33
|
+
| Gerar DPS | Produz XML 1.01, identificador, datas e valores formatados | SDK |
|
|
34
|
+
| Validar XSD | `prepararNota` valida o XML com os esquemas locais e `xmllint` | SDK + infraestrutura |
|
|
35
|
+
| Assinar | Assina a DPS e verifica a assinatura com o certificado fornecido | SDK |
|
|
36
|
+
| Transmitir | Compacta em GZip/Base64 e envia por HTTPS com autenticação mTLS | SDK |
|
|
37
|
+
| Autorizar | Aplica validações oficiais e retorna a NFS-e ou rejeições | SEFIN |
|
|
38
|
+
| Persistir e acompanhar | Armazenar XML, chave, identificador, erros, numeração e estado da emissão | Aplicação consumidora |
|
|
39
|
+
|
|
40
|
+
`emitirNfse` executa preparação e transmissão. `buildDpsFromJson` retorna XML **sem assinatura e sem executar o XSD**. `prepararNota` permite obter o XML assinado antes do envio; não o persiste. `transmitirNotaPreparada` confia no objeto recebido e não refaz as validações.
|
|
41
|
+
|
|
42
|
+
**Entrada XML:** passa pelo XSD e pela assinatura, mas não pela matriz fiscal do JSON. Assim, uma restrição do builder não significa necessariamente proibição no leiaute. O XML externo precisa ser montado e validado pelo integrador.
|
|
43
|
+
|
|
44
|
+
Base: [fluxo de emissão](/Users/tiagofonseca/priv_repo/nfse-sdk/emissaoNota.ts:57), [builder](/Users/tiagofonseca/priv_repo/nfse-sdk/dpsJson.ts:475), [cliente](/Users/tiagofonseca/priv_repo/nfse-sdk/client.ts:88).
|
|
45
|
+
|
|
46
|
+
## 3. Regras comuns a todas as emissões
|
|
47
|
+
|
|
48
|
+
### 3.1 Prestador, serviço e identificação
|
|
49
|
+
|
|
50
|
+
| ID | Regra implementada |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| COM-01 | Os blocos `prestador`, `servico` e `emissao` são obrigatórios no builder. |
|
|
53
|
+
| COM-02 | O prestador informa exatamente um identificador: `cnpj` com 14 dígitos ou `cpf` com 11. Não há verificação dos dígitos verificadores nem consulta cadastral. Pontuação e CNPJ alfanumérico são rejeitados pelo JSON atual. |
|
|
54
|
+
| COM-03 | `prestador.cLocEmi` tem 7 dígitos. O código não consulta a existência do município nem sua habilitação para emitir. |
|
|
55
|
+
| COM-04 | `prestador.serie` é obrigatória, com 1 a 5 dígitos, mesmo quando `emissao.serie` a sobrescreve. Não há restrição local de faixas reservadas por canal. |
|
|
56
|
+
| COM-05 | `emissao.nDPS` contém de 1 a 15 dígitos, começa de 1 a 9 e não aceita zero inicial. O SDK não incrementa nem reserva números. |
|
|
57
|
+
| COM-06 | O ID tem 45 caracteres: `DPS` + município (7) + tipo de inscrição (1) + CPF/CNPJ (14) + série (5) + número (15). Segmentos são completados com zeros à esquerda. `tpInsc` é derivado do documento; o campo legado informado é ignorado. |
|
|
58
|
+
| COM-07 | `servico.cTribNac` tem 6 dígitos. A descrição efetiva é obrigatória e não pode ser apenas espaços. `cNBS` é opcional, com 9 dígitos quando presente. Não se valida a correspondência entre descrição, código nacional e NBS. |
|
|
59
|
+
| COM-08 | `cLocPrestacao` exige 7 dígitos, inclusive na exportação. O builder não oferece `cPaisPrestacao`, embora o XSD permita essa alternativa. |
|
|
60
|
+
| COM-09 | A DPS sempre usa `tpEmit="1"`, emissão pelo prestador. Emissão por tomador/intermediário não é configurável no JSON. |
|
|
61
|
+
|
|
62
|
+
O serviço possui um único bloco, sem lista de itens. Não há modelagem de múltiplos serviços com códigos ou tratamentos fiscais distintos na mesma entrada.
|
|
63
|
+
|
|
64
|
+
### 3.2 Datas, ambiente e precedência
|
|
65
|
+
|
|
66
|
+
| Campo | Regra |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| `dhEmi` | Opcional. Sem valor, usa data/hora de São Paulo e offset `-03:00`. Quando informado, a pré-validação exige formato com offset numérico; `Z` é rejeitado. Essa etapa verifica formato, não toda a validade cronológica. |
|
|
69
|
+
| `dCompet` | Opcional. Sem valor, usa a parte da data de `dhEmi`. Quando informado, verifica uma data de calendário válida `AAAA-MM-DD`. |
|
|
70
|
+
| Relação entre datas | Não existe regra local para competência futura, competência posterior à emissão ou prazo retroativo. |
|
|
71
|
+
| Ambiente | `restrita` é o padrão e gera `tpAmb=2`; `producao` gera `tpAmb=1`. O cliente também aceita `sandbox` e `production`. |
|
|
72
|
+
| Série | `emissao.serie` prevalece sobre `prestador.serie`. |
|
|
73
|
+
| Descrição | `emissao.servico.xDescServ` prevalece sobre `emissao.xDescServ`, que prevalece sobre `servico.xDescServ`. |
|
|
74
|
+
| Local e NBS | Campos de `emissao.servico` prevalecem sobre os de `servico`. O código nacional continua vindo de `servico.cTribNac`. |
|
|
75
|
+
| Comércio exterior | `comercioExterior` prevalece sobre `comExt`; os dois objetos não são combinados. |
|
|
76
|
+
| Padrões do cliente | A chamada prevalece sobre os padrões. A combinação é superficial: informar `emissao.valores` substitui todo esse objeto, sem preservar seus campos internos anteriores. |
|
|
77
|
+
|
|
78
|
+
**Atenção ao ambiente:** na função direta `emitirNfse`, `options.ambiente` escolhe o destino, mas o XML JSON é construído usando `request.ambiente`. Valores diferentes podem gerar `tpAmb` incompatível com o destino. No cliente, `invoices.get` usa o ambiente do construtor, mesmo que uma emissão tenha sobrescrito o ambiente.
|
|
79
|
+
|
|
80
|
+
Base: [cadastros e datas](/Users/tiagofonseca/priv_repo/nfse-sdk/fiscalValidation.ts:186), [identificador](/Users/tiagofonseca/priv_repo/nfse-sdk/dpsJson.ts:290), [precedências](/Users/tiagofonseca/priv_repo/nfse-sdk/client.ts:88).
|
|
81
|
+
|
|
82
|
+
## 4. Matriz nacional × exterior
|
|
83
|
+
|
|
84
|
+
As regras desta seção descrevem o formato canônico, com valores dentro de `emissao.valores`. Há inconsistências com atalhos legados descritas na seção 10.
|
|
85
|
+
|
|
86
|
+
| Situação | Dados necessários | Resultado local |
|
|
87
|
+
| --- | --- | --- |
|
|
88
|
+
| Nacional, pessoa jurídica | `vServ`, CNPJ, nome e `endNac` | Aceito com demais blocos válidos. |
|
|
89
|
+
| Nacional, pessoa física | `vServ`, CPF, nome e `endNac` | Aceito com demais blocos válidos. |
|
|
90
|
+
| Nacional sem tomador | `vServ`; omitir todo o bloco `tomador` | Aceito. O SDK não define quando identificar o tomador é legalmente dispensável. |
|
|
91
|
+
| Nacional com tomador sem endereço | CPF/CNPJ e nome, sem `endNac` | Rejeitado. |
|
|
92
|
+
| Nacional com NIF ou endereço exterior | Mesmo que tenha valor em reais | Rejeitado. |
|
|
93
|
+
| Nacional com moeda/cotação ou país do resultado | Qualquer desses campos | Rejeitado no formato canônico. |
|
|
94
|
+
| Exportação com NIF | Comércio exterior completo, valor estrangeiro, cotação, país do resultado, NIF, nome e `endExt` | Aceito. |
|
|
95
|
+
| Exportação sem NIF, com justificativa | Trocar NIF por `cNaoNIF="1"` ou `"2"` | Aceito. `1` = dispensado; `2` = não exigência. |
|
|
96
|
+
| Exportação com `cNaoNIF="0"` | Não informado na nota de origem | Rejeitado pelo SDK, embora exista no XSD local. |
|
|
97
|
+
| Exportação sem tomador | Omitir todo o bloco `tomador` | Aceito localmente. |
|
|
98
|
+
| Exportação com CPF/CNPJ ou `endNac` | Identificação/endereço nacional no tomador | Rejeitado. |
|
|
99
|
+
| Exportação sem valor estrangeiro ou cotação | Mesmo que `vServ` esteja informado | Rejeitado. |
|
|
100
|
+
| Exportação com resultado `BR` | `tribISSQN="3"` e `cPaisResult="BR"` | Aceito pelo JSON e XSD; não há verificação material de exportação. |
|
|
101
|
+
| Cliente estrangeiro, operação tributável no Brasil | Tomador estrangeiro com `tribISSQN="1"` | Sem fluxo coerente no builder: sem comércio exterior o tomador é rejeitado; com o bloco, a matriz exige país do resultado, que só é permitido com código `3`. |
|
|
102
|
+
| Exportação com preço somente em reais | Apenas `vServ`, sem moeda/cotação | Sem suporte nesse formato. A exigência é do SDK, não uma conclusão sobre a legalidade da operação. |
|
|
103
|
+
| Serviço executado fisicamente no exterior | Local da prestação por país | Não representável por `cPaisPrestacao` no JSON atual. |
|
|
104
|
+
| Importação ou emissão pelo tomador | Prestador estrangeiro/emissor tomador | Não modelada pelo builder atual. |
|
|
105
|
+
|
|
106
|
+
### Identificação e endereço do tomador
|
|
107
|
+
|
|
108
|
+
Quando `tomador` existe, `xNome` e exatamente um entre `CNPJ`, `CPF`, `NIF` e `cNaoNIF` são exigidos. Informar dois identificadores é erro, mesmo que ambos sejam válidos.
|
|
109
|
+
|
|
110
|
+
| Endereço | Campos obrigatórios |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| Nacional | `endNac.cMun` (7 dígitos), `endNac.CEP` (8 dígitos), `xLgr`, `nro`, `xBairro` |
|
|
113
|
+
| Exterior | `endExt.cPais` (duas letras maiúsculas), `cEndPost`, `xCidade`, `xEstProvReg`, `xLgr`, `nro`, `xBairro` |
|
|
114
|
+
|
|
115
|
+
`xCpl`, telefone e e-mail são opcionais. `endNac` e `endExt` são mutuamente exclusivos. A pré-validação verifica o formato do país, mas não sua existência em catálogo, nem se é diferente de `BR`. País do tomador e país do resultado não precisam coincidir para passar localmente.
|
|
116
|
+
|
|
117
|
+
**Intermediário:** opcional; a interface pública e o XML suportam CPF ou CNPJ e nome. O validador genérico também reconhece NIF/`cNaoNIF`, mas o builder do intermediário não os serializa. Portanto, intermediário estrangeiro não tem suporte completo, mesmo que um objeto JavaScript passe pela pré-validação.
|
|
118
|
+
|
|
119
|
+
Base: [pessoas](/Users/tiagofonseca/priv_repo/nfse-sdk/fiscalValidation.ts:223), [matriz operacional](/Users/tiagofonseca/priv_repo/nfse-sdk/fiscalValidation.ts:409).
|
|
120
|
+
|
|
121
|
+
## 5. ISSQN, regimes e carga tributária
|
|
122
|
+
|
|
123
|
+
### 5.1 Natureza do ISSQN
|
|
124
|
+
|
|
125
|
+
`tributacaoMunicipal`, `tribISSQN` e `tpRetISSQN` são obrigatórios. Não existem valores fiscais padrão.
|
|
126
|
+
|
|
127
|
+
| `tribISSQN` | Significado no XSD local | Obrigatório | Proibido | Combinação atual |
|
|
128
|
+
| --- | --- | --- | --- | --- |
|
|
129
|
+
| `1` | Operação tributável | Tipo de retenção | País do resultado e tipo de imunidade | Nacional |
|
|
130
|
+
| `2` | Imunidade | Tipo de retenção e `tpImunidade` | País do resultado | Nacional |
|
|
131
|
+
| `3` | Exportação de serviço | Tipo de retenção e `cPaisResult` | Tipo de imunidade | Comércio exterior obrigatório pela matriz |
|
|
132
|
+
| `4` | Não incidência | Tipo de retenção | País do resultado e tipo de imunidade | Nacional |
|
|
133
|
+
|
|
134
|
+
`tpImunidade` aceita `0` a `5`: não especificada na origem; recíproca; templos; entidades previstas na alínea c; livros/jornais/periódicos; fonogramas/videofonogramas, respectivamente, conforme descrições do XSD. O SDK não comprova elegibilidade para nenhuma hipótese.
|
|
135
|
+
|
|
136
|
+
| `tpRetISSQN` | Declaração | Validação adicional existente |
|
|
137
|
+
| --- | --- | --- |
|
|
138
|
+
| `1` | Não retido | Nenhuma associação ao regime ou à natureza. |
|
|
139
|
+
| `2` | Retido pelo tomador | Não exige a presença do tomador. |
|
|
140
|
+
| `3` | Retido pelo intermediário | Não exige a presença do intermediário. |
|
|
141
|
+
|
|
142
|
+
A combinação de exportação, imunidade ou não incidência com retenção não é barrada pela pré-validação. Aceitar o código não confirma que a retenção se aplica ao caso.
|
|
143
|
+
|
|
144
|
+
`pAliq` é proibida para não optante (`opSimpNac="1"`). Para MEI e ME/EPP, passa na pré-validação se for decimal não negativo e não ultrapassar `9.99`; é serializada com duas casas. Esse limite é estrutural, não uma autorização fiscal de qualquer alíquota até esse valor. `vBC` e `vISSQN` nesse bloco são rejeitados: o SDK não os transmite como campos da DPS.
|
|
145
|
+
|
|
146
|
+
### 5.2 Regime do prestador e total aproximado de tributos
|
|
147
|
+
|
|
148
|
+
| `opSimpNac` | Perfil | Única forma de `totTrib` aceita pelo JSON |
|
|
149
|
+
| --- | --- | --- |
|
|
150
|
+
| `1` | Não optante | Os três percentuais: `pTotTribFed`, `pTotTribEst`, `pTotTribMun` |
|
|
151
|
+
| `2` | MEI | Somente `indTotTrib="0"` |
|
|
152
|
+
| `3` | ME/EPP do Simples | Somente `pTotTribSN` |
|
|
153
|
+
|
|
154
|
+
A tabela vale tanto para nacional quanto para exterior. `totTrib` ausente, vazio, com modalidades misturadas ou com percentual federal/estadual/municipal incompleto é rejeitado.
|
|
155
|
+
|
|
156
|
+
Embora os tipos e o builder tenham `vTotTribFed/Est/Mun`, **nenhum dos três regimes válidos permite essa modalidade no validador JSON atual**. A restrição por regime é mais estreita que a escolha estrutural do XSD.
|
|
157
|
+
|
|
158
|
+
A carga aproximada não é o ISS devido nem o valor líquido da nota. O SDK não a busca em tabelas, não a calcula e não a zera automaticamente na exportação. Também não valida a soma dos percentuais ou sua adequação ao serviço.
|
|
159
|
+
|
|
160
|
+
`regApTribSN` é opcional e permitido somente para ME/EPP: `1` = tributos federais e ISS no Simples; `2` = federais no Simples e ISS fora; `3` = ambos fora. O valor não altera a regra de `totTrib`, que continua exigindo `pTotTribSN`.
|
|
161
|
+
|
|
162
|
+
`regEspTrib` é obrigatório e aceita: `0` nenhum; `1` ato cooperado; `2` estimativa; `3` microempresa municipal; `4` notário/registrador; `5` autônomo; `6` sociedade de profissionais; `9` outros. Não há cruzamento com serviço, município ou opção pelo Simples.
|
|
163
|
+
|
|
164
|
+
Base: [ISSQN](/Users/tiagofonseca/priv_repo/nfse-sdk/fiscalValidation.ts:297), [totais](/Users/tiagofonseca/priv_repo/nfse-sdk/fiscalValidation.ts:336), [domínios locais](/Users/tiagofonseca/priv_repo/nfse-sdk/schemas/nfse/v1.01/Schemas/1.01/tiposSimples_v1.01.xsd:996).
|
|
165
|
+
|
|
166
|
+
## 6. Valores e comércio exterior
|
|
167
|
+
|
|
168
|
+
### 6.1 Conversão e arredondamento
|
|
169
|
+
|
|
170
|
+
| ID | Regra |
|
|
171
|
+
| --- | --- |
|
|
172
|
+
| VAL-01 | `vServ`, `vServMoeda` e cotação, quando usados na validação de valores, precisam ser decimais maiores que zero. Não se aceitam vírgula decimal, sinal negativo ou notação exponencial. |
|
|
173
|
+
| VAL-02 | Se `vServ` estiver informado, ele prevalece. Caso contrário, calcula-se `vServMoeda × cotacao`, arredondado para duas casas. |
|
|
174
|
+
| VAL-03 | A multiplicação usa inteiros de precisão arbitrária após converter as entradas em texto. A cotação tem tipo `number`: a precisão já perdida antes de chegar ao SDK não é recuperada. |
|
|
175
|
+
| VAL-04 | Valores monetários, alíquotas e percentuais normalmente são arredondados para duas casas, com metade para cima. Exemplo: `1.005 → 1.01`. |
|
|
176
|
+
| VAL-05 | Exceção: `comExt.vServMoeda` é transmitido como recebido, sem arredondamento. Três casas podem passar no JSON e falhar no XSD. |
|
|
177
|
+
| VAL-06 | Não se confere se `vServ` corresponde ao produto da moeda pela cotação. Não se confere se o valor estrangeiro de `comercioExterior` coincide com o usado na conversão. |
|
|
178
|
+
| VAL-07 | A cotação não é transmitida em uma tag própria, não é consultada externamente e não tem fonte/data registradas pelo SDK. |
|
|
179
|
+
| VAL-08 | Um valor positivo muito pequeno pode arredondar para zero: `0.001 → 0.00`. Não existe segunda validação de positividade após arredondar. |
|
|
180
|
+
|
|
181
|
+
Exemplo confirmado: `9000.00 × 5.210621 = 46895.59` no XML. Informar simultaneamente `vServ="1.00"` e os mesmos dados cambiais faz o SDK transmitir `1.00`, sem apontar divergência.
|
|
182
|
+
|
|
183
|
+
### 6.2 Dados de comércio exterior
|
|
184
|
+
|
|
185
|
+
Todos os campos abaixo são obrigatórios quando o bloco está presente, exceto o valor dentro do próprio bloco, que pode vir de `valores.vServMoeda`. O preenchimento apenas de `comercioExterior.vServMoeda` não satisfaz a exigência de valor/cotação da matriz operacional.
|
|
186
|
+
|
|
187
|
+
| Campo | Domínio do XSD local | Aplicação da regra |
|
|
188
|
+
| --- | --- | --- |
|
|
189
|
+
| `mdPrestacao` | `0`, `1`, `2`, `3`, `4` | Modo de prestação. Há divergência nas descrições dos códigos `3` e `4` entre os dois arquivos XSD; não usar o exemplo do repositório como escolha fiscal automática. |
|
|
190
|
+
| `vincPrest` | `0` sem vínculo; `1` controlada; `2` controladora; `3` coligada; `4` matriz; `5` filial/sucursal; `6` outro; `9` desconhecido | Relação entre as partes. |
|
|
191
|
+
| `tpMoeda` | Três dígitos, código de moeda conforme tabela BACEN | O SDK não consulta o catálogo; não recebe `USD`/`EUR` nesse campo. |
|
|
192
|
+
| `vServMoeda` | Decimal do leiaute, até 15 dígitos inteiros e escala prevista no XSD | Prefere o valor do bloco; na ausência, usa o valor da emissão. |
|
|
193
|
+
| `mecAFComexP` | `00` a `08` | Apoio/fomento do prestador; `01` significa nenhum. |
|
|
194
|
+
| `mecAFComexT` | `00` a `26` | Apoio/fomento do tomador; `01` significa nenhum. |
|
|
195
|
+
| `movTempBens` | `0` desconhecido; `1` não; `2` vinculado à declaração de importação; `3` vinculado à declaração de exportação | O JSON não oferece `nDI` nem `nRE`, existentes no XSD. |
|
|
196
|
+
| `mdic` | `0` não compartilhar; `1` compartilhar | Declaração de compartilhamento com a Secretaria de Comércio Exterior. |
|
|
197
|
+
|
|
198
|
+
A pré-validação exige presença desses códigos; a verificação dos respectivos domínios fica principalmente no XSD. `comercioExterior.cPaisResult` existe no tipo, mas é ignorado na geração do XML: o campo efetivo fica em `tributacaoMunicipal.cPaisResult`.
|
|
199
|
+
|
|
200
|
+
Base: [cálculo](/Users/tiagofonseca/priv_repo/nfse-sdk/dpsJson.ts:243), [comércio exterior](/Users/tiagofonseca/priv_repo/nfse-sdk/dpsJson.ts:459), [estrutura local](/Users/tiagofonseca/priv_repo/nfse-sdk/schemas/nfse/v1.01/Schemas/1.01/tiposComplexos_v1.01.xsd:1364).
|
|
201
|
+
|
|
202
|
+
## 7. Tributos federais e funcionalidades especiais
|
|
203
|
+
|
|
204
|
+
`tributacaoFederal` é opcional. Quando `piscofins` existe, `CST` é obrigatório; base, alíquotas, valores e retenção são opcionais na pré-validação.
|
|
205
|
+
|
|
206
|
+
| Informação | Comportamento |
|
|
207
|
+
| --- | --- |
|
|
208
|
+
| CST de PIS/COFINS | Aceita `00–09`, `49–56`, `60–67`, `70–75`, `98` e `99`. Não escolhe o CST conforme nacional/exterior nem verifica a adequação à operação. |
|
|
209
|
+
| Base, alíquotas, PIS e COFINS | Valida decimais não negativos e formata com duas casas. Não calcula `base × alíquota`, nem exige os campos conforme o CST. |
|
|
210
|
+
| `tpRetPisCofins` | Transmitido quando informado; domínio `0–9` validado pelo XSD, sem cruzamento local com os valores. |
|
|
211
|
+
| `vRetCP`, `vRetIRRF`, `vRetCSLL` | Transmitidos e arredondados; não passam pela mesma validação fiscal antecipada dos valores de PIS/COFINS. Conteúdo inválido pode falhar posteriormente no builder/XSD. |
|
|
212
|
+
| Valor líquido | Não calculado; retenções não são automaticamente subtraídas de `vServ`. |
|
|
213
|
+
|
|
214
|
+
No XSD, os tipos de retenção federal são: `0` nenhum dos três tributos retido; `1` PIS/COFINS retidos; `2` PIS/COFINS não retidos; `3` os três retidos; `4` PIS/COFINS retidos e CSLL não; `5` somente PIS; `6` somente COFINS; `7` COFINS/CSLL; `8` somente CSLL; `9` PIS/CSLL. Os códigos `1` e `2` não detalham CSLL como os demais.
|
|
215
|
+
|
|
216
|
+
| Caso especial | Suporte atual no JSON |
|
|
217
|
+
| --- | --- |
|
|
218
|
+
| IBS/CBS | `tribNac` é rejeitado. O grupo oficial `IBSCBS` não é construído. |
|
|
219
|
+
| Descontos | `valores.vDesc` é rejeitado, inclusive zero. |
|
|
220
|
+
| Deduções/reduções | `valores.vDedRed` é rejeitado, inclusive zero. |
|
|
221
|
+
| Obra com `cObra` | Pode gerar XML válido. |
|
|
222
|
+
| Obra vazia ou somente inscrição imobiliária | Passa pela pré-validação, mas falta identificação exigida pelo XSD. |
|
|
223
|
+
| Obra com `cObra` e `inscImobFisc` | O builder coloca os elementos na ordem errada; falha no XSD. |
|
|
224
|
+
| Obra com `cCM` preenchido | Rejeitada; `cCIB` e endereço da obra não são oferecidos pelo builder. |
|
|
225
|
+
| Atividade/evento artístico, cultural etc. | `emissao.evento` é rejeitado; o formato legado não representa o grupo oficial. |
|
|
226
|
+
| Suspensão de exigibilidade, benefício municipal, código tributário municipal e informações complementares | Não há campos correspondentes no modelo JSON atual. |
|
|
227
|
+
| Cancelamento e outros eventos fiscais | Existe envio de XML de evento pronto; não há regra de elegibilidade, prazo, motivo ou builder de cancelamento. Não confundir com `emissao.evento`. |
|
|
228
|
+
| Substituição de NFS-e | Sem fluxo dedicado/modelagem no JSON. |
|
|
229
|
+
|
|
230
|
+
A ausência de suporte a IBS/CBS não permite concluir que sua omissão seja válida em qualquer emissão atual. O portal oficial mantém documentação de produção, esquemas e anexos próprios; esta análise verificou o código e os esquemas locais, sem certificar aderência integral a todas as atualizações publicadas. [Fonte: documentação técnica de produção da NFS-e](https://www.gov.br/nfse/pt-br/biblioteca/documentacao-tecnica/documentacao-atual).
|
|
231
|
+
|
|
232
|
+
Base: [validação federal e funcionalidades bloqueadas](/Users/tiagofonseca/priv_repo/nfse-sdk/fiscalValidation.ts:384), [serialização de tributos](/Users/tiagofonseca/priv_repo/nfse-sdk/dpsJson.ts:385), [obra no XSD](/Users/tiagofonseca/priv_repo/nfse-sdk/schemas/nfse/v1.01/Schemas/1.01/tiposComplexos_v1.01.xsd:1517).
|
|
233
|
+
|
|
234
|
+
## 8. Autorização, erros e continuidade
|
|
235
|
+
|
|
236
|
+
| Resultado | Como identificar | Tratamento de produto recomendado |
|
|
237
|
+
| --- | --- | --- |
|
|
238
|
+
| JSON inválido | Relatório `valid=false` ou `DpsFiscalValidationError` | Mostrar campo e motivo; corrigir antes do envio. |
|
|
239
|
+
| XML incompatível | `DpsXsdValidationError` | Corrigir estrutura/formato ou a geração do XML. |
|
|
240
|
+
| Validador indisponível | `XmllintUnavailableError` | Tratar como falha de infraestrutura, sem atribuí-la ao preenchimento do usuário. |
|
|
241
|
+
| Falha de assinatura/certificado | Erro na leitura do PFX, assinatura ou verificação | Corrigir o material do certificado; a rotina fiscal específica precisa ser chamada explicitamente. |
|
|
242
|
+
| Rejeição da SEFIN | `EmitirNotaError` com status, DPS, corpo e erros normalizados | Preservar `Codigo`, `Descricao` e `Complemento`; apresentar ação conforme o motivo. |
|
|
243
|
+
| Sucesso HTTP sem XML da nota | Também gera `EmitirNotaError` | Não marcar como autorizada apenas pelo HTTP 2xx. |
|
|
244
|
+
| Sucesso com XML compactado | HTTP 2xx + `nfseXmlGZipB64`/`NfseXmlGZipB64`; descompactação bem-sucedida | Guardar XML, chave e DPS. |
|
|
245
|
+
| Falha de rede/timeout | Erro de transporte; timeout configurado em 60 segundos | Tratar o resultado como potencialmente indeterminado; conciliar antes de decidir um novo envio. |
|
|
246
|
+
|
|
247
|
+
O relatório fiscal tem `code`, `path`, severidade, origem, mensagem e, em alguns casos, sugestão. Atualmente todos os problemas gerados têm severidade `error`, origem `sdk`, e `warnings` vem vazio. `normalizedPayload` é a entrada original, sem normalização efetiva. A API pressupõe os blocos estruturais tipados; JSON arbitrário pode provocar erro comum antes de produzir relatório.
|
|
248
|
+
|
|
249
|
+
A chave é lida do corpo da resposta ou do atributo `Id="NFS..."` do XML. Se não for encontrada, o retorno ainda pode ser considerado sucesso com chave vazia. O SDK não verifica a assinatura da NFS-e recebida nem impõe validação da chave retornada.
|
|
250
|
+
|
|
251
|
+
Não existem armazenamento, estados persistentes, idempotência, controle de concorrência, fila ou retentativa automática. A consulta exposta usa chave de acesso; não há método de consulta por ID da DPS. A aplicação precisa definir como conciliar uma emissão cujo envio teve resposta incerta.
|
|
252
|
+
|
|
253
|
+
**Certificado:** `assertCertificateForProvider` verifica vigência e busca o CPF/CNPJ do prestador nos dados do certificado, mas não é chamada por `emitirNfse`, `prepararNota` ou `transmitirNotaPreparada`. A verificação criptográfica da assinatura não substitui essa checagem de titularidade/vigência.
|
|
254
|
+
|
|
255
|
+
Base: [respostas](/Users/tiagofonseca/priv_repo/nfse-sdk/emissaoNota.ts:89), [certificado](/Users/tiagofonseca/priv_repo/nfse-sdk/certificateValidation.ts:15), [XSD](/Users/tiagofonseca/priv_repo/nfse-sdk/xsdValidation.ts:67), [transporte e erros](/Users/tiagofonseca/priv_repo/nfse-sdk/sefinClient.ts:205).
|
|
256
|
+
|
|
257
|
+
## 9. Catálogo de cenários para produto e QA
|
|
258
|
+
|
|
259
|
+
Os eixos abaixo são combináveis. A aceitação local de uma combinação não equivale à autorização fiscal.
|
|
260
|
+
|
|
261
|
+
| Eixo | Casos a distinguir | Cobertura atual |
|
|
262
|
+
| --- | --- | --- |
|
|
263
|
+
| Prestador | CPF; CNPJ; ambos; nenhum; formato inválido | Aceita exatamente um documento numérico no formato previsto. |
|
|
264
|
+
| Regime | Não optante; MEI; ME/EPP; código desconhecido | Três regimes válidos, cada um com modalidade exclusiva de `totTrib`. |
|
|
265
|
+
| Operação | Nacional tributável; imune; não incidência; exportação; estrangeiro tributável; importação | Primeiros quatro representáveis; últimos dois sem fluxo JSON adequado. |
|
|
266
|
+
| Tomador nacional | PJ; PF; ausente; documento duplicado; endereço ausente/exterior | PJ/PF com endereço nacional ou bloco ausente. |
|
|
267
|
+
| Tomador exterior | NIF; dispensado; não exigido; ausente; CPF/CNPJ; endereço ausente/nacional | NIF ou justificativas `1/2` com endereço exterior, ou bloco ausente. |
|
|
268
|
+
| Retenção ISS | Sem retenção; tomador; intermediário | Códigos aceitos sem dependência de existência do responsável. |
|
|
269
|
+
| Valores | Reais; conversão; ambos; zero; negativo; vírgula; excesso de casas; divergência cambial | Ver regras VAL-01 a VAL-08. |
|
|
270
|
+
| Países | Resultado exterior; resultado Brasil; código malformado; país do tomador diferente | Verifica formato; não resolve a classificação material. |
|
|
271
|
+
| Tributos federais | Bloco ausente; CST isolado; base/alíquotas/valores; retenções | Representação declaratória, sem cálculo ou cruzamento tributário. |
|
|
272
|
+
| Recursos especiais | Obra; evento; desconto; dedução; IBS/CBS; cancelamento; substituição | Suporte parcial ou ausente, conforme seção 7. |
|
|
273
|
+
| Ciclo operacional | Preparação; falha local; autorização; rejeição; rede incerta; consulta; evento | SDK transporta e retorna dados; aplicação gerencia o ciclo. |
|
|
274
|
+
|
|
275
|
+
**Duas configurações de referência, sem prescrever enquadramento fiscal:**
|
|
276
|
+
|
|
277
|
+
- Nacional: prestador e serviço válidos; `vServ="1000.00"`; tomador CNPJ + nome + endereço nacional; `tribISSQN="1"`, `tpRetISSQN="1"`; modalidade de `totTrib` correspondente ao regime.
|
|
278
|
+
- Exterior: mesmos blocos comuns; tomador NIF + nome + endereço exterior; `vServMoeda="1000.00"`, cotação `5`; comércio exterior com códigos aplicáveis; `tribISSQN="3"`, país do resultado `US`, `tpRetISSQN="1"`; modalidade de `totTrib` correspondente ao regime. Sem `vServ` explícito, gera `5000.00` reais.
|
|
279
|
+
|
|
280
|
+
Os números e códigos ilustram formatos. A escolha fiscal continua dependendo da operação e do cadastro efetivos.
|
|
281
|
+
|
|
282
|
+
## 10. Lacunas confirmadas e decisões prioritárias
|
|
283
|
+
|
|
284
|
+
As ações desta seção são recomendações; não representam mudanças implementadas nesta análise.
|
|
285
|
+
|
|
286
|
+
| Prioridade | Achado | Evidência / impacto | Decisão recomendada |
|
|
287
|
+
| --- | --- | --- | --- |
|
|
288
|
+
| Alta | Comércio exterior implica exportação de ISS | Não há caminho JSON coerente para estrangeiro tributável; `cPaisResult=BR` passa como exportação | Separar país do cliente, local da prestação, local do resultado e tratamento do ISS. |
|
|
289
|
+
| Alta | Valores cambiais podem divergir | `vServ=1.00` pode coexistir com `1000.00 × 5`; valor estrangeiro do bloco também pode ser diferente | Definir fonte única dos valores e política explícita de divergência. |
|
|
290
|
+
| Alta | Ambiente do XML pode divergir do destino | `options.ambiente` sobrescreve o envio depois da geração | Resolver um único ambiente antes de construir a DPS e manter a consulta consistente. |
|
|
291
|
+
| Alta | Validação de certificado desconectada | Rotina existe, mas não integra emissão/preparação/transmissão | Definir política de titularidade/representação e aplicar a checagem no ponto apropriado. |
|
|
292
|
+
| Alta | Cobertura incompleta do leiaute | IBS/CBS, prestação por país, descontos, deduções e outros grupos ausentes | Definir escopo comercial suportado e evolução do modelo a partir dos cenários reais. |
|
|
293
|
+
| Média | Atalhos e `valores` não seguem a mesma regra | A matriz usa o objeto `valores` inteiro; outras validações usam fallback campo a campo. Nacional com atalhos de câmbio pode passar; exportação com dados divididos pode falhar | Normalizar a entrada antes de validar. |
|
|
294
|
+
| Média | Obra com inscrição gera ordem inválida | `cObra` é serializado antes de `inscImobFisc`; XSD exige a ordem inversa | Corrigir ordem e validar o grupo antes da geração. |
|
|
295
|
+
| Média | Pré-validação aceita valores que falham depois | Moeda estrangeira com três casas e obra vazia passam no JSON e falham no XSD | Alinhar a validação antecipada à saída efetiva. |
|
|
296
|
+
| Média | Retenção não exige responsável | Retido pelo tomador/intermediário é aceito sem essas pessoas | Explicitar dependências conforme regras oficiais aplicáveis. |
|
|
297
|
+
| Média | Sucesso pode vir sem chave | HTTP 2xx com XML válido para descompressão pode retornar chave vazia | Definir resultado incompleto e validações mínimas da resposta. |
|
|
298
|
+
| Média | Documentação diverge do código | README usa exportação sem comércio exterior e país `BR`; exemplo do cliente omite endereço. JSON_MAPPING descreve CNPJ obrigatório, `tpInsc` e totais de forma incompatível com a implementação | Atualizar exemplos e tabelas a partir de casos executáveis. |
|
|
299
|
+
| Média | Descrições de modo de prestação divergem nos XSD locais | Tipos simples e complexos atribuem significados diferentes aos códigos `3/4` | Conferir o domínio oficial aplicável antes de publicar rótulos de produto. |
|
|
300
|
+
|
|
301
|
+
Além dessas lacunas, a camada consumidora precisa assumir decisões ainda inexistentes: elegibilidade cadastral e municipal, correlação entre códigos fiscais, justificativa da natureza tributária, política cambial, numeração concorrente, persistência, conciliação e tratamento de rejeições.
|
|
302
|
+
|
|
303
|
+
## 11. Evidência e limites da verificação
|
|
304
|
+
|
|
305
|
+
A análise cruzou validadores, builders, transmissão, cliente, testes, documentação interna e os XSD 1.01 distribuídos no repositório. Em divergências, o comportamento executável foi usado como referência do produto atual.
|
|
306
|
+
|
|
307
|
+
**Verificações executadas:**
|
|
308
|
+
|
|
309
|
+
- **25 testes existentes passaram**, cobrindo JSON, XSD, erros de infraestrutura do validador, ambientes e compactação.
|
|
310
|
+
- **83 cenários adicionais foram executados:** 63 combinações de operação, regime, retenção e identificação do tomador; 20 casos de borda. Os resultados confirmaram as aceitações e rejeições descritas, incluindo país `BR` em exportação, divergências cambiais, atalhos mistos, obra e arredondamento para zero.
|
|
311
|
+
- Os cenários aceitos pela pré-validação também foram submetidos ao XSD, distinguindo sucesso no JSON de sucesso estrutural.
|
|
312
|
+
|
|
313
|
+
`npm test` não pôde ser executado pelo comando padrão: o ambiente não tinha `npm` nem as dependências do projeto instaladas. Os 25 testes foram executados em cópia temporária, com remoção de tipos pelo Node disponível no aplicativo e exportação dos módulos necessários. Isso não substitui compilação TypeScript nem a suíte completa de assinatura, certificado, cliente e transporte.
|
|
314
|
+
|
|
315
|
+
Nenhuma nota foi transmitida, nenhum certificado real foi utilizado e não houve homologação com a SEFIN. As evidências demonstram comportamento local, não aceitação em produção. O código de emissão não foi alterado.
|
|
316
|
+
|
|
317
|
+
**Referências de manutenção:** [validador fiscal](/Users/tiagofonseca/priv_repo/nfse-sdk/fiscalValidation.ts), [modelo e XML](/Users/tiagofonseca/priv_repo/nfse-sdk/dpsJson.ts), [testes de regras](/Users/tiagofonseca/priv_repo/nfse-sdk/test/dpsJson.test.ts), [testes de XSD](/Users/tiagofonseca/priv_repo/nfse-sdk/test/xsdValidation.test.ts), [matriz interna anterior](/Users/tiagofonseca/priv_repo/nfse-sdk/docs/FISCAL_MATRIX.md), [mapeamento anterior](/Users/tiagofonseca/priv_repo/nfse-sdk/JSON_MAPPING.md).
|
package/examples/README.md
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Copyable entry points for common NFS-e Nacional flows.
|
|
4
4
|
|
|
5
|
+
The payloads in `payloads.ts` are shared by these examples and exercised by the JSON/XSD test suite. They include domestic and export declarations. Running the XML generator requires no certificate; the issuing examples do.
|
|
6
|
+
|
|
5
7
|
## Files
|
|
6
8
|
|
|
9
|
+
- [`payloads.ts`](./payloads.ts): reusable, tested domestic and export JSON payloads.
|
|
7
10
|
- [`generate-dps-xml.ts`](./generate-dps-xml.ts): build an unsigned DPS XML from JSON.
|
|
8
11
|
- [`emit-homologation.ts`](./emit-homologation.ts): emit in the restricted/sandbox SEFIN environment.
|
|
9
12
|
- [`client-resource.ts`](./client-resource.ts): use `NfseClient` with certificate and defaults configured once.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NfseClient } from '@useinvio/nfse-sdk';
|
|
2
|
+
import { nationalInvoice } from './payloads.js';
|
|
2
3
|
|
|
3
4
|
const client = new NfseClient({
|
|
4
5
|
environment: 'sandbox',
|
|
@@ -6,45 +7,10 @@ const client = new NfseClient({
|
|
|
6
7
|
content: process.env.NFSE_CERTIFICATE_BASE64!,
|
|
7
8
|
password: process.env.NFSE_CERTIFICATE_PASSWORD!,
|
|
8
9
|
},
|
|
9
|
-
defaults: {
|
|
10
|
-
prestador: {
|
|
11
|
-
cnpj: '12345678000195',
|
|
12
|
-
tpInsc: '2',
|
|
13
|
-
cLocEmi: '4106902',
|
|
14
|
-
serie: '1601',
|
|
15
|
-
opSimpNac: '1',
|
|
16
|
-
regEspTrib: '0',
|
|
17
|
-
},
|
|
18
|
-
servico: {
|
|
19
|
-
cTribNac: '010201',
|
|
20
|
-
xDescServ: 'Desenvolvimento de software',
|
|
21
|
-
cLocPrestacao: '4106902',
|
|
22
|
-
cNBS: '115022000',
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
const invoice = await client.invoices.create({
|
|
28
|
-
emissao: {
|
|
29
|
-
nDPS: '2',
|
|
30
|
-
valores: { vServ: '1000.00' },
|
|
31
|
-
tomador: {
|
|
32
|
-
CPF: '00000000000',
|
|
33
|
-
xNome: 'Cliente Exemplo',
|
|
34
|
-
},
|
|
35
|
-
tributacaoMunicipal: {
|
|
36
|
-
tribISSQN: '3',
|
|
37
|
-
tpRetISSQN: '1',
|
|
38
|
-
},
|
|
39
|
-
tributacaoFederal: {
|
|
40
|
-
piscofins: { CST: '07' },
|
|
41
|
-
},
|
|
42
|
-
totTrib: {
|
|
43
|
-
pTotTribFed: '0.00',
|
|
44
|
-
pTotTribEst: '0.00',
|
|
45
|
-
pTotTribMun: '5.00',
|
|
46
|
-
},
|
|
47
|
-
},
|
|
10
|
+
defaults: { prestador: nationalInvoice.prestador, servico: nationalInvoice.servico },
|
|
48
11
|
});
|
|
49
12
|
|
|
13
|
+
const invoice = await client.invoices.create({ emissao: nationalInvoice.emissao });
|
|
50
14
|
console.log(invoice.chaveAcesso);
|
|
15
|
+
// If create overrides ambiente, pass that same environment when querying:
|
|
16
|
+
// await client.invoices.get(invoice.chaveAcesso, { ambiente: 'restrita' });
|
|
@@ -1,46 +1,11 @@
|
|
|
1
|
-
import { EmitirNotaError, emitirNfse, loadPfx
|
|
1
|
+
import { EmitirNotaError, emitirNfse, loadPfx } from '@useinvio/nfse-sdk';
|
|
2
|
+
import { nationalInvoice } from './payloads.js';
|
|
2
3
|
|
|
3
4
|
const pfx = loadPfx('./certificado.pfx', process.env.PFX_PASSWORD!);
|
|
4
5
|
|
|
5
|
-
const nota: DpsJsonRequest = {
|
|
6
|
-
ambiente: 'restrita',
|
|
7
|
-
prestador: {
|
|
8
|
-
cnpj: '12345678000195',
|
|
9
|
-
tpInsc: '2',
|
|
10
|
-
cLocEmi: '4106902',
|
|
11
|
-
serie: '1601',
|
|
12
|
-
opSimpNac: '1',
|
|
13
|
-
regEspTrib: '0',
|
|
14
|
-
},
|
|
15
|
-
servico: {
|
|
16
|
-
cTribNac: '010201',
|
|
17
|
-
xDescServ: 'Desenvolvimento de software',
|
|
18
|
-
cLocPrestacao: '4106902',
|
|
19
|
-
cNBS: '115022000',
|
|
20
|
-
},
|
|
21
|
-
emissao: {
|
|
22
|
-
nDPS: '1',
|
|
23
|
-
dhEmi: '2026-06-15T10:30:00-03:00',
|
|
24
|
-
dCompet: '2026-06-01',
|
|
25
|
-
valores: { vServ: '1500.00' },
|
|
26
|
-
tributacaoMunicipal: {
|
|
27
|
-
tribISSQN: '3',
|
|
28
|
-
cPaisResult: 'BR',
|
|
29
|
-
tpRetISSQN: '1',
|
|
30
|
-
},
|
|
31
|
-
tributacaoFederal: {
|
|
32
|
-
piscofins: { CST: '07' },
|
|
33
|
-
},
|
|
34
|
-
totTrib: {
|
|
35
|
-
pTotTribFed: '0.00',
|
|
36
|
-
pTotTribEst: '0.00',
|
|
37
|
-
pTotTribMun: '5.00',
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
6
|
|
|
42
7
|
try {
|
|
43
|
-
const resultado = await emitirNfse(
|
|
8
|
+
const resultado = await emitirNfse(nationalInvoice, pfx);
|
|
44
9
|
console.log(resultado.chaveAcesso);
|
|
45
10
|
console.log(resultado.nfseXml);
|
|
46
11
|
} catch (error) {
|