@sinete/nfe 0.2.0 → 0.4.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/README.md +6 -2
- package/dist/build/build.d.ts +8 -1
- package/dist/build/build.d.ts.map +1 -1
- package/dist/build/textos.d.ts +26 -0
- package/dist/build/textos.d.ts.map +1 -0
- package/dist/ibs-cbs.d.ts +5 -0
- package/dist/ibs-cbs.d.ts.map +1 -1
- package/dist/ibs-cbs.js.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +233 -33
- package/dist/index.js.map +9 -8
- package/dist/ports.d.ts +18 -0
- package/dist/ports.d.ts.map +1 -1
- package/dist/rtc.d.ts.map +1 -1
- package/dist/services/recuperar.d.ts +3 -2
- package/dist/services/recuperar.d.ts.map +1 -1
- package/dist/services/resolver.d.ts +4 -3
- package/dist/services/resolver.d.ts.map +1 -1
- package/dist/versao-gerada.d.ts +1 -1
- package/package.json +9 -9
- package/src/build/build.ts +31 -24
- package/src/build/textos.ts +228 -0
- package/src/ibs-cbs.ts +5 -0
- package/src/index.ts +7 -1
- package/src/ports.ts +19 -0
- package/src/rtc.ts +50 -9
- package/src/services/recuperar.ts +4 -2
- package/src/services/resolver.ts +5 -3
- package/src/versao-gerada.ts +1 -1
package/dist/ports.d.ts
CHANGED
|
@@ -84,12 +84,30 @@ export interface PedidoIbsCbsNota {
|
|
|
84
84
|
readonly tpOperGov: string;
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Alíquota do IBS/CBS que entrou no cálculo de um item vinda de quem integra (`comAliquotasInformadas`), e não da tabela
|
|
89
|
+
* oficial do pacote.
|
|
90
|
+
*/
|
|
91
|
+
export interface AliquotaIbsCbsInformada {
|
|
92
|
+
/** Número do item na nota (1 a 990). */
|
|
93
|
+
readonly nItem: number;
|
|
94
|
+
readonly tributo: 'CBS' | 'IBSUF' | 'IBSMun';
|
|
95
|
+
/** Percentual nominal informado (`'8.7'` = 8,7%). */
|
|
96
|
+
readonly valor: string;
|
|
97
|
+
/** O motivo declarado em `comAliquotasInformadas`. */
|
|
98
|
+
readonly motivo: string;
|
|
99
|
+
}
|
|
87
100
|
/** Resultado da calculadora: o grupo `IBSCBS` de cada item pedido, já na forma lexical do leiaute. */
|
|
88
101
|
export interface RespostaIbsCbs {
|
|
89
102
|
readonly itens: readonly {
|
|
90
103
|
readonly nItem: number;
|
|
91
104
|
readonly IBSCBS: TTribNFe;
|
|
92
105
|
}[];
|
|
106
|
+
/**
|
|
107
|
+
* As alíquotas que não vieram da tabela oficial: a montagem as repassa em `NfeMontada.aliquotasInformadas`. Ausente
|
|
108
|
+
* ou vazio quando todas foram oficiais; a calculadora de fora do sinete que não sabe dizer pode omitir.
|
|
109
|
+
*/
|
|
110
|
+
readonly aliquotasInformadas?: readonly AliquotaIbsCbsInformada[];
|
|
93
111
|
/**
|
|
94
112
|
* Problemas de classificação ou de dado (`caminho` relativo ao item, como `itens[2].impostos.ibsCbs`). A ocorrência sem
|
|
95
113
|
* `origem` entra como `montagem` (ADR 0011); marque `entrada` a que aponta um valor da nota.
|
package/dist/ports.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../src/ports.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../src/ports.ts"],"names":[],"mappings":"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"}
|
package/dist/rtc.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rtc.d.ts","sourceRoot":"","sources":["../src/rtc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,KAAK,EAGV,eAAe,EAIhB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"rtc.d.ts","sourceRoot":"","sources":["../src/rtc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,KAAK,EAGV,eAAe,EAIhB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAEV,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB,6DAA6D;AAC7D,MAAM,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC;AAEpE,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IACjC,gIAAgI;IAChI,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,KAAK,MAAM,CAAC;IAC3E;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;QAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACrG,wGAAwG;IACxG,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AAmBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,GAAG,eAAe,CAQvE;AA+DD;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAAC,aAAa,CAAC,CASjE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,uBAA4B,GAAG,iBAAiB,CAYzF"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* função lê o evento de lá e só o dá como registrado quando o retorno dele diz 135, 136 ou 155 para a mesma chave e o
|
|
9
9
|
* mesmo tipo.
|
|
10
10
|
*/
|
|
11
|
-
import type { ClienteNfe, EventoRegistrado, ResultadoConsulta } from './client.js';
|
|
11
|
+
import type { ClienteNfe, EnvioOpcoes, EventoRegistrado, ResultadoConsulta } from './client.js';
|
|
12
12
|
/** Resultado da recuperação: o evento registrado, com a consulta que o prova, ou só a consulta. */
|
|
13
13
|
export type RecuperacaoEvento = {
|
|
14
14
|
readonly registrado: true;
|
|
@@ -23,6 +23,7 @@ export type RecuperacaoEvento = {
|
|
|
23
23
|
* vários, como na CC-e; com `nSeqEvento`, só o dessa sequência). Serve depois de um pedido de evento sem resposta ou
|
|
24
24
|
* respondido com 573 ou 580: nunca conclua que o evento existe só pelo `cStat` do pedido. `registrado: false` quer
|
|
25
25
|
* dizer que a consulta não mostrou o evento (ou não decidiu: veja `consulta`); não quer dizer que o evento não existe.
|
|
26
|
+
* `opcoes.signal` cancela a consulta.
|
|
26
27
|
*/
|
|
27
|
-
export declare function recuperarEventoRegistrado(cliente: ClienteNfe, chave: string, tpEvento: string, nSeqEvento?: number): Promise<RecuperacaoEvento>;
|
|
28
|
+
export declare function recuperarEventoRegistrado(cliente: ClienteNfe, chave: string, tpEvento: string, nSeqEvento?: number, opcoes?: EnvioOpcoes): Promise<RecuperacaoEvento>;
|
|
28
29
|
//# sourceMappingURL=recuperar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recuperar.d.ts","sourceRoot":"","sources":["../../src/services/recuperar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"recuperar.d.ts","sourceRoot":"","sources":["../../src/services/recuperar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIhG,mGAAmG;AACnG,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAA;CAAE,GACtG;IAAE,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAkDzE;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAW5B"}
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* Acesso [chNFe: ...]") e serviço de consulta protocolo (cStat 217; 561, 562 e 613 quando a numeração tem outra NF-e).
|
|
27
27
|
*/
|
|
28
28
|
import type { Recusado } from '@sinete/core';
|
|
29
|
-
import type { ClienteNfe, ResultadoAutorizacao, ResultadoConsulta } from './client.js';
|
|
29
|
+
import type { ClienteNfe, EnvioOpcoes, ResultadoAutorizacao, ResultadoConsulta } from './client.js';
|
|
30
30
|
/**
|
|
31
31
|
* O que o `digVal` do protocolo diz dos bytes assinados: `confere` (é o DigestValue deles), `sem-digval` (o protocolo
|
|
32
32
|
* não o traz) ou `difere` (a SEFAZ registrou outro conteúdo com a mesma chave).
|
|
@@ -82,7 +82,8 @@ export type ResolucaoEnvio =
|
|
|
82
82
|
export declare function chaveDaDuplicidade(xMotivo: string): string | undefined;
|
|
83
83
|
/**
|
|
84
84
|
* Resolve um envio de autorização sem resposta, ou cuja resposta foi 204 ou 539, consultando a chave da NF-e
|
|
85
|
-
* assinada. `anterior` é o desfecho do envio, quando houve um.
|
|
85
|
+
* assinada. `anterior` é o desfecho do envio, quando houve um. `opcoes.signal` cancela a consulta (lança o
|
|
86
|
+
* `ErroTransporte` com `code: 'cancelado'`).
|
|
86
87
|
*/
|
|
87
|
-
export declare function resolverEnvioSemResposta(cliente: ClienteNfe, nfeAssinada: string, anterior?: ResultadoAutorizacao): Promise<ResolucaoEnvio>;
|
|
88
|
+
export declare function resolverEnvioSemResposta(cliente: ClienteNfe, nfeAssinada: string, anterior?: ResultadoAutorizacao, opcoes?: EnvioOpcoes): Promise<ResolucaoEnvio>;
|
|
88
89
|
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/services/resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,KAAK,EAAE,UAAU,EAAgB,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/services/resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAgB,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIlH;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEtE,yFAAyF;AACzF,MAAM,MAAM,cAAc;AACxB;;;;GAIG;AACD;IACE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,WAAW,GAAG,UAAU,CAAC;IAC3D,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,SAAS,EAAE,oBAAoB,CAAC;CAC1C;AACH,gFAAgF;GAC9E;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE;AAC7D;;;GAGG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,iBAAiB,CAAC;CAC/C;AACH;;;;GAIG;GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,WAAW,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAA;CAAE;AACrH;;;GAGG;GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAK3E,mGAAmG;AACnG,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEtE;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,UAAU,EACnB,WAAW,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,CAAC,CAiCzB"}
|
package/dist/versao-gerada.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sinete/nfe",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "NF-e modelo 55: modelo de entrada tipado, montagem com totais em decimal exato, validação antes de assinar, autorização, consultas, eventos, inutilização, contingência SVC e Distribuição DF-e",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nfe",
|
|
@@ -44,16 +44,16 @@
|
|
|
44
44
|
"build": "bun ../../scripts/build.ts ."
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@sinete/core": "^0.
|
|
48
|
-
"@sinete/ibs-cbs": "^0.2.
|
|
49
|
-
"@sinete/ibs-cbs-dados": "
|
|
50
|
-
"@sinete/rejeicoes": "^0.
|
|
51
|
-
"@sinete/schemas": "^0.2.
|
|
52
|
-
"@sinete/transport": "^0.2.
|
|
53
|
-
"@sinete/validators": "^0.2.
|
|
47
|
+
"@sinete/core": "^0.3.0",
|
|
48
|
+
"@sinete/ibs-cbs": "^0.2.1",
|
|
49
|
+
"@sinete/ibs-cbs-dados": ">=2026.9.3",
|
|
50
|
+
"@sinete/rejeicoes": "^0.3.0",
|
|
51
|
+
"@sinete/schemas": "^0.2.1",
|
|
52
|
+
"@sinete/transport": "^0.2.1",
|
|
53
|
+
"@sinete/validators": "^0.2.1"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@sinete/sefaz-sim": "^0.2.
|
|
56
|
+
"@sinete/sefaz-sim": "^0.2.1"
|
|
57
57
|
},
|
|
58
58
|
"publishConfig": {
|
|
59
59
|
"access": "public"
|
package/src/build/build.ts
CHANGED
|
@@ -50,7 +50,7 @@ import type {
|
|
|
50
50
|
Referenciada,
|
|
51
51
|
ResponsavelTecnico,
|
|
52
52
|
} from '../model.ts';
|
|
53
|
-
import type { CalculadoraIbsCbs, PedidoIbsCbsItem } from '../ports.ts';
|
|
53
|
+
import type { AliquotaIbsCbsInformada, CalculadoraIbsCbs, PedidoIbsCbsItem } from '../ports.ts';
|
|
54
54
|
import { calculadoraIbsCbs } from '../rtc.ts';
|
|
55
55
|
import type { Instante } from '../time.ts';
|
|
56
56
|
import { deslocamentoDaUf, formatarDh } from '../time.ts';
|
|
@@ -70,6 +70,7 @@ import {
|
|
|
70
70
|
} from './nfce.ts';
|
|
71
71
|
import { camposForaDoPl, escolherPl } from './pl.ts';
|
|
72
72
|
import { cstComIsento, vencimentos } from './rejeicoes.ts';
|
|
73
|
+
import { conferirTextosDaEntrada, textoXmlValido } from './textos.ts';
|
|
73
74
|
import { buildIcmsUfDest, buildIi, buildIpi, buildIssqn, buildPisCofins, buildPisCofinsSt } from './tributos.ts';
|
|
74
75
|
import type { Familia } from './values.ts';
|
|
75
76
|
import { Ctx, clean, digits, TOLERANCIA } from './values.ts';
|
|
@@ -158,6 +159,13 @@ export interface NfeMontada {
|
|
|
158
159
|
readonly infNFe: TNFe_infNFe;
|
|
159
160
|
/** `<NFe xmlns="...">` com o `infNFe` canônico, sem assinatura, já validado contra o schema. */
|
|
160
161
|
readonly xml: string;
|
|
162
|
+
/**
|
|
163
|
+
* Alíquotas do IBS/CBS que a calculadora usou vindas de quem integra (`comAliquotasInformadas`), e não da tabela
|
|
164
|
+
* oficial do pacote, por item. Ausente quando todas foram oficiais. A montagem não recusa por isso: é o caminho para
|
|
165
|
+
* emitir com uma alíquota já publicada antes de o pacote trazê-la. Guarde junto com a nota e alerte quem opera; em
|
|
166
|
+
* produção, a alíquota informada é responsabilidade de quem a informou.
|
|
167
|
+
*/
|
|
168
|
+
readonly aliquotasInformadas?: readonly AliquotaIbsCbsInformada[];
|
|
161
169
|
}
|
|
162
170
|
|
|
163
171
|
export type ResultadoMontagemNfe =
|
|
@@ -344,25 +352,10 @@ function referencia(ref: Referenciada, path: string, issues: Issues): TNFe_infNF
|
|
|
344
352
|
} as TNFe_infNFe_ide_NFref;
|
|
345
353
|
}
|
|
346
354
|
|
|
347
|
-
/** Produção `Char` do XML 1.0: tab, LF, CR, U+0020 a U+D7FF, U+E000 a U+FFFD e U+10000 a U+10FFFF. */
|
|
348
|
-
function textoXmlValido(texto: string): boolean {
|
|
349
|
-
for (const ch of texto) {
|
|
350
|
-
const c = ch.codePointAt(0) ?? 0;
|
|
351
|
-
const ok =
|
|
352
|
-
c === 0x9 ||
|
|
353
|
-
c === 0xa ||
|
|
354
|
-
c === 0xd ||
|
|
355
|
-
(c >= 0x20 && c <= 0xd7ff) ||
|
|
356
|
-
(c >= 0xe000 && c <= 0xfffd) ||
|
|
357
|
-
(c >= 0x10000 && c <= 0x10ffff);
|
|
358
|
-
if (!ok) return false;
|
|
359
|
-
}
|
|
360
|
-
return true;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
355
|
/**
|
|
364
|
-
* Texto com caractere que o XML não representa
|
|
365
|
-
*
|
|
356
|
+
* Texto com caractere que o XML não representa vira ocorrência com o caminho do campo, em vez de falhar no parse do
|
|
357
|
+
* documento montado. Os textos da entrada já foram conferidos com o caminho dela (`conferirTextosDaEntrada`): aqui só
|
|
358
|
+
* sobra o que veio das opções da montagem.
|
|
366
359
|
*/
|
|
367
360
|
function textosForaDoXml(value: unknown, path: string, issues: Issues): void {
|
|
368
361
|
if (typeof value === 'string') {
|
|
@@ -863,6 +856,7 @@ export async function montarNfe(entrada: DadosNfe, opcoes: MontarNfeOpcoes): Pro
|
|
|
863
856
|
const classificados = entrada.itens
|
|
864
857
|
.map((it, n) => ({ it, n }))
|
|
865
858
|
.filter(({ it }) => it.impostos.ibsCbs?.classificacao !== undefined);
|
|
859
|
+
let aliquotasInformadas: readonly AliquotaIbsCbsInformada[] = [];
|
|
866
860
|
if (classificados.length > 0) {
|
|
867
861
|
const calculadora = opcoes.ibsCbs ?? calculadoraPadrao();
|
|
868
862
|
const reqs: PedidoIbsCbsItem[] = classificados.map(({ it, n }) => {
|
|
@@ -939,14 +933,19 @@ export async function montarNfe(entrada: DadosNfe, opcoes: MontarNfeOpcoes): Pro
|
|
|
939
933
|
itens: reqs,
|
|
940
934
|
});
|
|
941
935
|
issues.addAll(resp.ocorrencias ?? [], 'montagem');
|
|
936
|
+
aliquotasInformadas = resp.aliquotasInformadas ?? [];
|
|
937
|
+
// A calculadora que recusou já disse por quê: o grupo que faltar é consequência da ocorrência dela, e uma segunda
|
|
938
|
+
// ocorrência por item repetiria a causa. `ibscbs_calculo` fica para a calculadora que omite um item sem explicar.
|
|
939
|
+
const explicou = (resp.ocorrencias?.length ?? 0) > 0;
|
|
942
940
|
for (const { n } of classificados) {
|
|
943
941
|
const g = resp.itens.find((x) => x.nItem === n + 1);
|
|
944
942
|
if (g === undefined) {
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
943
|
+
if (!explicou)
|
|
944
|
+
issues.montagem(
|
|
945
|
+
`itens[${n}].impostos.ibsCbs`,
|
|
946
|
+
'ibscbs_calculo',
|
|
947
|
+
'a calculadora não devolveu o grupo IBSCBS do item',
|
|
948
|
+
);
|
|
950
949
|
continue;
|
|
951
950
|
}
|
|
952
951
|
((itens[n] as ItemMontado).det.imposto as Record<string, unknown>).IBSCBS = g.IBSCBS;
|
|
@@ -971,6 +970,13 @@ export async function montarNfe(entrada: DadosNfe, opcoes: MontarNfeOpcoes): Pro
|
|
|
971
970
|
grupoInvalido(TISCt as ComplexType, 'IS', imp.IS, is, issues);
|
|
972
971
|
}
|
|
973
972
|
});
|
|
973
|
+
// Texto e tamanho dos campos de texto pelo tipo do PL, com o caminho da entrada (ADR 0011); o campo que outra
|
|
974
|
+
// conferência já recusou fica só com a ocorrência dela.
|
|
975
|
+
// Em homologação, o nome do destinatário e, na NFC-e, a descrição do primeiro item são as literais da E04-20 e da I04-10:
|
|
976
|
+
// o texto informado não vai ao XML.
|
|
977
|
+
const substituidos =
|
|
978
|
+
opcoes.ambiente === 'homologacao' ? ['destinatario.xNome', ...(nfce ? ['itens[0].produto.xProd'] : [])] : [];
|
|
979
|
+
conferirTextosDaEntrada(entrada, pl.infNFe as ComplexType, issues, new Set(substituidos));
|
|
974
980
|
if (!issues.empty) return { ok: false, ocorrencias: issues.classificadas };
|
|
975
981
|
|
|
976
982
|
// Totais (grupo W)
|
|
@@ -1425,6 +1431,7 @@ export async function montarNfe(entrada: DadosNfe, opcoes: MontarNfeOpcoes): Pro
|
|
|
1425
1431
|
pl: pl.vigencia,
|
|
1426
1432
|
infNFe: inf,
|
|
1427
1433
|
xml,
|
|
1434
|
+
...(aliquotasInformadas.length === 0 ? {} : { aliquotasInformadas }),
|
|
1428
1435
|
},
|
|
1429
1436
|
};
|
|
1430
1437
|
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Texto e tamanho dos campos de texto da NF-e conferidos na entrada (ADR 0011, revisão de 01/10/2026).
|
|
3
|
+
*
|
|
4
|
+
* Antes, o caractere que o XML não representa e o texto fora do tipo do leiaute (tamanho, espaço nas pontas,
|
|
5
|
+
* caractere fora do `TString`) só apareciam na montagem, com o caminho do XML (`infNFe.det[0].prod.xProd` ou
|
|
6
|
+
* `/infNFe/det[1]/prod/xProd`). Conferidos aqui, saem como `campo_invalido`, com `origem: 'entrada'`, o caminho da
|
|
7
|
+
* entrada (`itens[0].produto.xProd`) e uma mensagem para quem preenche o campo (`no máximo 60 caracteres`), sem nome
|
|
8
|
+
* de validador nem de tipo do XSD.
|
|
9
|
+
*
|
|
10
|
+
* O tipo de cada campo vem do schema do PL da montagem (o `TString` com o `maxLength` do elemento), nunca de um número
|
|
11
|
+
* escrito aqui: a tabela abaixo só diz qual elemento do `infNFe` recebe cada campo da entrada.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { ComplexType, OcorrenciaSchema, Particle, SimpleType } from '@sinete/schemas';
|
|
15
|
+
import { conferirTipoSimples, ehComplexType, ehElementParticle, ehWildcard } from '@sinete/schemas';
|
|
16
|
+
import type { Issues } from '../issues.ts';
|
|
17
|
+
import type { DadosNfe } from '../model.ts';
|
|
18
|
+
|
|
19
|
+
/** Produção `Char` do XML 1.0: tab, LF, CR, U+0020 a U+D7FF, U+E000 a U+FFFD e U+10000 a U+10FFFF. */
|
|
20
|
+
export function textoXmlValido(texto: string): boolean {
|
|
21
|
+
for (const ch of texto) {
|
|
22
|
+
const c = ch.codePointAt(0) ?? 0;
|
|
23
|
+
const ok =
|
|
24
|
+
c === 0x9 ||
|
|
25
|
+
c === 0xa ||
|
|
26
|
+
c === 0xd ||
|
|
27
|
+
(c >= 0x20 && c <= 0xd7ff) ||
|
|
28
|
+
(c >= 0xe000 && c <= 0xfffd) ||
|
|
29
|
+
(c >= 0x10000 && c <= 0x10ffff);
|
|
30
|
+
if (!ok) return false;
|
|
31
|
+
}
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Campo de texto da entrada (com `[]` onde a entrada é uma lista) e o elemento do `infNFe` que o recebe como veio. Só
|
|
37
|
+
* os campos copiados sem transformação: o que a montagem calcula ou formata é conferido por ela.
|
|
38
|
+
*/
|
|
39
|
+
const CAMPOS: readonly (readonly [entrada: string, xml: string])[] = [
|
|
40
|
+
['natOp', 'ide.natOp'],
|
|
41
|
+
['emitente.xNome', 'emit.xNome'],
|
|
42
|
+
['emitente.xFant', 'emit.xFant'],
|
|
43
|
+
['emitente.endereco.xLgr', 'emit.enderEmit.xLgr'],
|
|
44
|
+
['emitente.endereco.nro', 'emit.enderEmit.nro'],
|
|
45
|
+
['emitente.endereco.xCpl', 'emit.enderEmit.xCpl'],
|
|
46
|
+
['emitente.endereco.xBairro', 'emit.enderEmit.xBairro'],
|
|
47
|
+
['emitente.endereco.xMun', 'emit.enderEmit.xMun'],
|
|
48
|
+
['destinatario.xNome', 'dest.xNome'],
|
|
49
|
+
['destinatario.email', 'dest.email'],
|
|
50
|
+
['destinatario.endereco.xLgr', 'dest.enderDest.xLgr'],
|
|
51
|
+
['destinatario.endereco.nro', 'dest.enderDest.nro'],
|
|
52
|
+
['destinatario.endereco.xCpl', 'dest.enderDest.xCpl'],
|
|
53
|
+
['destinatario.endereco.xBairro', 'dest.enderDest.xBairro'],
|
|
54
|
+
['destinatario.endereco.xMun', 'dest.enderDest.xMun'],
|
|
55
|
+
['destinatario.endereco.xPais', 'dest.enderDest.xPais'],
|
|
56
|
+
...(['retirada', 'entrega'] as const).flatMap((g) =>
|
|
57
|
+
(['xNome', 'xLgr', 'nro', 'xCpl', 'xBairro', 'xMun', 'email'] as const).map(
|
|
58
|
+
(c) => [`${g}.${c}`, `${g}.${c}`] as const,
|
|
59
|
+
),
|
|
60
|
+
),
|
|
61
|
+
['itens[].produto.cProd', 'det.prod.cProd'],
|
|
62
|
+
['itens[].produto.xProd', 'det.prod.xProd'],
|
|
63
|
+
['itens[].produto.uCom', 'det.prod.uCom'],
|
|
64
|
+
['itens[].produto.uTrib', 'det.prod.uTrib'],
|
|
65
|
+
['itens[].produto.xPed', 'det.prod.xPed'],
|
|
66
|
+
['itens[].infAdProd', 'det.infAdProd'],
|
|
67
|
+
['transporte.transportador.xNome', 'transp.transporta.xNome'],
|
|
68
|
+
['transporte.transportador.xEnder', 'transp.transporta.xEnder'],
|
|
69
|
+
['transporte.transportador.xMun', 'transp.transporta.xMun'],
|
|
70
|
+
['transporte.volumes[].esp', 'transp.vol.esp'],
|
|
71
|
+
['transporte.volumes[].marca', 'transp.vol.marca'],
|
|
72
|
+
['transporte.volumes[].nVol', 'transp.vol.nVol'],
|
|
73
|
+
['cobranca.fatura.nFat', 'cobr.fat.nFat'],
|
|
74
|
+
['cobranca.duplicatas[].nDup', 'cobr.dup.nDup'],
|
|
75
|
+
['pagamento.detPag[].xPag', 'pag.detPag.xPag'],
|
|
76
|
+
['informacoesAdicionais.infAdFisco', 'infAdic.infAdFisco'],
|
|
77
|
+
['informacoesAdicionais.infCpl', 'infAdic.infCpl'],
|
|
78
|
+
['informacoesAdicionais.obsCont[].xTexto', 'infAdic.obsCont.xTexto'],
|
|
79
|
+
['informacoesAdicionais.obsFisco[].xTexto', 'infAdic.obsFisco.xTexto'],
|
|
80
|
+
['compra.xNEmp', 'compra.xNEmp'],
|
|
81
|
+
['compra.xPed', 'compra.xPed'],
|
|
82
|
+
['compra.xCont', 'compra.xCont'],
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
/** O tipo do elemento `nome` entre as partículas (sequências e escolhas aninhadas). */
|
|
86
|
+
function elemento(p: Particle | undefined, nome: string): ComplexType | SimpleType | undefined {
|
|
87
|
+
if (p === undefined || ehWildcard(p)) return undefined;
|
|
88
|
+
if (ehElementParticle(p)) return p.e === nome ? p.t : undefined;
|
|
89
|
+
for (const i of p.i) {
|
|
90
|
+
const t = elemento(i, nome);
|
|
91
|
+
if (t !== undefined) return t;
|
|
92
|
+
}
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** O tipo simples do elemento em `caminho` (pontos) a partir do `infNFe`; `undefined` se o PL não o tem. */
|
|
97
|
+
function tipoEm(infNFe: ComplexType, caminho: string): SimpleType | undefined {
|
|
98
|
+
let t: ComplexType | SimpleType | undefined = infNFe;
|
|
99
|
+
for (const nome of caminho.split('.')) {
|
|
100
|
+
if (t === undefined || !ehComplexType(t)) return undefined;
|
|
101
|
+
t = elemento(t.c, nome);
|
|
102
|
+
}
|
|
103
|
+
return t === undefined || ehComplexType(t) ? undefined : t;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const tiposPorPl = new WeakMap<ComplexType, ReadonlyMap<string, SimpleType>>();
|
|
107
|
+
|
|
108
|
+
/** Tipo de cada campo da tabela no PL, calculado uma vez por PL. */
|
|
109
|
+
function tiposDoPl(infNFe: ComplexType): ReadonlyMap<string, SimpleType> {
|
|
110
|
+
let m = tiposPorPl.get(infNFe);
|
|
111
|
+
if (m === undefined) {
|
|
112
|
+
const novo = new Map<string, SimpleType>();
|
|
113
|
+
for (const [entrada, xml] of CAMPOS) {
|
|
114
|
+
const t = tipoEm(infNFe, xml);
|
|
115
|
+
if (t !== undefined) novo.set(entrada, t);
|
|
116
|
+
}
|
|
117
|
+
m = novo;
|
|
118
|
+
tiposPorPl.set(infNFe, m);
|
|
119
|
+
}
|
|
120
|
+
return m;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Os valores de `caminho` (com `[]` nas listas) na entrada, com o caminho concreto de cada um. */
|
|
124
|
+
function valoresEm(raiz: unknown, caminho: string): [string, unknown][] {
|
|
125
|
+
let atuais: [string, unknown][] = [['', raiz]];
|
|
126
|
+
for (const parte of caminho.split('.')) {
|
|
127
|
+
const lista = parte.endsWith('[]');
|
|
128
|
+
const chave = lista ? parte.slice(0, -2) : parte;
|
|
129
|
+
const proximos: [string, unknown][] = [];
|
|
130
|
+
for (const [c, v] of atuais) {
|
|
131
|
+
if (typeof v !== 'object' || v === null) continue;
|
|
132
|
+
const filho = (v as Record<string, unknown>)[chave];
|
|
133
|
+
const base = c === '' ? chave : `${c}.${chave}`;
|
|
134
|
+
if (!lista) proximos.push([base, filho]);
|
|
135
|
+
else if (Array.isArray(filho)) for (const [n, f] of filho.entries()) proximos.push([`${base}[${n}]`, f]);
|
|
136
|
+
}
|
|
137
|
+
atuais = proximos;
|
|
138
|
+
}
|
|
139
|
+
return atuais;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Caminhos de todos os textos da entrada com caractere que o XML não representa. */
|
|
143
|
+
function textosForaDoXml(valor: unknown, caminho: string, saida: string[]): void {
|
|
144
|
+
if (typeof valor === 'string') {
|
|
145
|
+
if (!textoXmlValido(valor)) saida.push(caminho);
|
|
146
|
+
} else if (Array.isArray(valor)) {
|
|
147
|
+
for (const [n, v] of valor.entries()) textosForaDoXml(v, `${caminho}[${n}]`, saida);
|
|
148
|
+
} else if (typeof valor === 'object' && valor !== null) {
|
|
149
|
+
for (const [k, v] of Object.entries(valor)) textosForaDoXml(v, caminho === '' ? k : `${caminho}.${k}`, saida);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Mensagem do caractere que não vai ao documento e que a pessoa não consegue ver (controle, invisível). */
|
|
154
|
+
const CARACTERE_INVISIVEL = 'caractere não aceito (símbolo ou caractere de controle)';
|
|
155
|
+
|
|
156
|
+
/** Caractere que a pessoa enxerga: letra, marca, número, pontuação ou símbolo. */
|
|
157
|
+
const VISIVEL = /^[\p{L}\p{M}\p{N}\p{P}\p{S}]$/u;
|
|
158
|
+
|
|
159
|
+
/** O primeiro caractere de `valor` que o tipo não aceita no meio de um texto, ou `undefined` se todos passam. */
|
|
160
|
+
function caractereRecusado(tipo: SimpleType, valor: string): string | undefined {
|
|
161
|
+
for (const ch of new Set(valor)) {
|
|
162
|
+
const saida: OcorrenciaSchema[] = [];
|
|
163
|
+
conferirTipoSimples(tipo, `A${ch}A`, '', saida);
|
|
164
|
+
if (saida.some((o) => o.code === 'padrao')) return ch;
|
|
165
|
+
}
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* As regras do tipo que `valor` viola, em texto para quem preenche o campo. O código do validador decide a regra; a
|
|
171
|
+
* mensagem diz o limite (do próprio tipo) e, no `padrao`, se o problema é o espaço nas pontas ou um caractere.
|
|
172
|
+
*/
|
|
173
|
+
function mensagensDoTexto(tipo: SimpleType, valor: string, violadas: readonly OcorrenciaSchema[]): string[] {
|
|
174
|
+
if (violadas.length === 0) return [];
|
|
175
|
+
if (valor.trim() === '') return ['não pode ficar em branco'];
|
|
176
|
+
const tamanho = [...valor].length;
|
|
177
|
+
const mensagens = new Set<string>();
|
|
178
|
+
for (const o of violadas) {
|
|
179
|
+
if (o.code === 'tamanho_maximo' && tipo.mx !== undefined)
|
|
180
|
+
mensagens.add(`no máximo ${tipo.mx} caracteres (tem ${tamanho})`);
|
|
181
|
+
else if (o.code === 'tamanho_minimo' && tipo.mn !== undefined)
|
|
182
|
+
mensagens.add(`no mínimo ${tipo.mn} caracteres (tem ${tamanho})`);
|
|
183
|
+
else if (o.code === 'tamanho' && tipo.l !== undefined)
|
|
184
|
+
mensagens.add(`exatamente ${tipo.l} caracteres (tem ${tamanho})`);
|
|
185
|
+
else if (o.code === 'padrao') {
|
|
186
|
+
const espaco = valor !== valor.trim();
|
|
187
|
+
const ch = caractereRecusado(tipo, valor);
|
|
188
|
+
if (espaco) mensagens.add('sem espaço no começo nem no fim');
|
|
189
|
+
if (ch !== undefined) mensagens.add(VISIVEL.test(ch) ? `caractere não aceito: “${ch}”` : CARACTERE_INVISIVEL);
|
|
190
|
+
if (!espaco && ch === undefined) mensagens.add('formato não aceito');
|
|
191
|
+
} else mensagens.add('valor não aceito neste campo');
|
|
192
|
+
}
|
|
193
|
+
return [...mensagens];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Confere os textos da entrada: em qualquer campo, o caractere que o XML não representa; nos campos da tabela, o tipo
|
|
198
|
+
* do elemento no PL (tamanho, espaço nas pontas, caractere fora do conjunto aceito). Tudo sai como `campo_invalido`,
|
|
199
|
+
* com o caminho da entrada, `origem: 'entrada'` e uma ocorrência por regra violada. O campo que já tem ocorrência (de
|
|
200
|
+
* outra conferência da entrada) não ganha outra. `substituidos` são os campos que a montagem troca por um texto fixo
|
|
201
|
+
* (o nome do destinatário em homologação): o tipo deles não é conferido, porque o texto informado não vai ao XML.
|
|
202
|
+
*/
|
|
203
|
+
export function conferirTextosDaEntrada(
|
|
204
|
+
entrada: DadosNfe,
|
|
205
|
+
infNFe: ComplexType,
|
|
206
|
+
issues: Issues,
|
|
207
|
+
substituidos: ReadonlySet<string> = new Set(),
|
|
208
|
+
): void {
|
|
209
|
+
const jaRecusados = new Set(issues.list.map((i) => i.caminho));
|
|
210
|
+
const foraDoXml: string[] = [];
|
|
211
|
+
textosForaDoXml(entrada, '', foraDoXml);
|
|
212
|
+
for (const c of foraDoXml) {
|
|
213
|
+
if (jaRecusados.has(c) || substituidos.has(c)) continue;
|
|
214
|
+
issues.add(c, 'campo_invalido', CARACTERE_INVISIVEL);
|
|
215
|
+
jaRecusados.add(c);
|
|
216
|
+
}
|
|
217
|
+
const tipos = tiposDoPl(infNFe);
|
|
218
|
+
for (const [campo] of CAMPOS) {
|
|
219
|
+
const tipo = tipos.get(campo);
|
|
220
|
+
if (tipo === undefined) continue;
|
|
221
|
+
for (const [caminho, valor] of valoresEm(entrada, campo)) {
|
|
222
|
+
if (typeof valor !== 'string' || jaRecusados.has(caminho) || substituidos.has(caminho)) continue;
|
|
223
|
+
const saida: OcorrenciaSchema[] = [];
|
|
224
|
+
conferirTipoSimples(tipo, valor, caminho, saida);
|
|
225
|
+
for (const m of mensagensDoTexto(tipo, valor, saida)) issues.add(caminho, 'campo_invalido', m);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
package/src/ibs-cbs.ts
CHANGED
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
* embarcado não entra aqui, para não ir para o bundle de quem não o usa: `carregarDatasetEmbarcado()`, na raiz do
|
|
8
8
|
* `@sinete/nfe`, o importa sob demanda. `Dec`, `DataIso` e `Vigencia` vêm do motor (os de `Dec` e `DataIso` são os
|
|
9
9
|
* mesmos; a `Vigencia` dos dados, com os campos do dataset, fica acessível pelos tipos que a usam).
|
|
10
|
+
*
|
|
11
|
+
* Experimental (ADR 0016, seção 5) até o `@sinete/ibs-cbs` sair 1.0: a calculadora espera a norma da base de cálculo
|
|
12
|
+
* (NT 2025.002, UB16-10), e este subpath pode mudar em minor, sempre com changeset.
|
|
13
|
+
*
|
|
14
|
+
* @experimental
|
|
10
15
|
*/
|
|
11
16
|
|
|
12
17
|
// biome-ignore lint/performance/noReExportAll: o subpath existe para reexportar o motor inteiro, e as duas pontas são do mesmo repo.
|
package/src/index.ts
CHANGED
|
@@ -107,7 +107,13 @@ export type {
|
|
|
107
107
|
Volume,
|
|
108
108
|
} from './model.ts';
|
|
109
109
|
export { MotivoDesoneracaoIcms, TipoPagamento } from './model.ts';
|
|
110
|
-
export type {
|
|
110
|
+
export type {
|
|
111
|
+
AliquotaIbsCbsInformada,
|
|
112
|
+
CalculadoraIbsCbs,
|
|
113
|
+
PedidoIbsCbsItem,
|
|
114
|
+
PedidoIbsCbsNota,
|
|
115
|
+
RespostaIbsCbs,
|
|
116
|
+
} from './ports.ts';
|
|
111
117
|
export { rotuloDoCaminho } from './rotulo.ts';
|
|
112
118
|
export type { CalculadoraIbsCbsOpcoes, GrupoIbsCbs } from './rtc.ts';
|
|
113
119
|
export { calculadoraIbsCbs, carregarDatasetEmbarcado, localDaOperacao } from './rtc.ts';
|
package/src/ports.ts
CHANGED
|
@@ -74,9 +74,28 @@ export interface PedidoIbsCbsNota {
|
|
|
74
74
|
readonly compraGov?: { readonly tpEnteGov: string; readonly pRedutor: Decimal; readonly tpOperGov: string };
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Alíquota do IBS/CBS que entrou no cálculo de um item vinda de quem integra (`comAliquotasInformadas`), e não da tabela
|
|
79
|
+
* oficial do pacote.
|
|
80
|
+
*/
|
|
81
|
+
export interface AliquotaIbsCbsInformada {
|
|
82
|
+
/** Número do item na nota (1 a 990). */
|
|
83
|
+
readonly nItem: number;
|
|
84
|
+
readonly tributo: 'CBS' | 'IBSUF' | 'IBSMun';
|
|
85
|
+
/** Percentual nominal informado (`'8.7'` = 8,7%). */
|
|
86
|
+
readonly valor: string;
|
|
87
|
+
/** O motivo declarado em `comAliquotasInformadas`. */
|
|
88
|
+
readonly motivo: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
77
91
|
/** Resultado da calculadora: o grupo `IBSCBS` de cada item pedido, já na forma lexical do leiaute. */
|
|
78
92
|
export interface RespostaIbsCbs {
|
|
79
93
|
readonly itens: readonly { readonly nItem: number; readonly IBSCBS: TTribNFe }[];
|
|
94
|
+
/**
|
|
95
|
+
* As alíquotas que não vieram da tabela oficial: a montagem as repassa em `NfeMontada.aliquotasInformadas`. Ausente
|
|
96
|
+
* ou vazio quando todas foram oficiais; a calculadora de fora do sinete que não sabe dizer pode omitir.
|
|
97
|
+
*/
|
|
98
|
+
readonly aliquotasInformadas?: readonly AliquotaIbsCbsInformada[];
|
|
80
99
|
/**
|
|
81
100
|
* Problemas de classificação ou de dado (`caminho` relativo ao item, como `itens[2].impostos.ibsCbs`). A ocorrência sem
|
|
82
101
|
* `origem` entra como `montagem` (ADR 0011); marque `entrada` a que aponta um valor da nota.
|