ghinfe 0.6.0 → 0.6.2
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/.env.example +24 -15
- package/LICENSE +21 -21
- package/README.md +491 -413
- package/docs/developer-guide.html +421 -421
- package/docs/openapi.yaml +428 -428
- package/examples/dce-homologacao.js +141 -0
- package/examples/emitir-nfce.js +51 -51
- package/examples/emitir-nfe.js +83 -83
- package/examples/emitir-nfse.js +46 -46
- package/examples/endpoints-sefaz.js +14 -14
- package/examples/eventos-nfe.js +49 -49
- package/examples/gerar-chave.js +25 -25
- package/examples/gerar-dace.js +59 -0
- package/examples/gerar-danfe.js +75 -75
- package/examples/gerar-dce.js +58 -0
- package/examples/layouts-nfse.js +51 -51
- package/examples/mock-sefaz.js +52 -52
- package/examples/nfse-eventos.js +57 -57
- package/examples/reforma-ibscbs.js +27 -27
- package/examples/reforma-nfe-xml.js +52 -52
- package/examples/status-sefaz.js +12 -12
- package/examples/validar-xsd.js +48 -48
- package/package.json +59 -68
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/consSitDCeTiposBasico_v1.00.xsd +123 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/consSitDCe_v1.00.xsd +10 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/consStatServDCeTiposBasico_v1.00.xsd +110 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/consStatServDCe_v1.00.xsd +10 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/dceTiposBasico_v1.00.xsd +1388 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/retConsSitDCe_v1.00.xsd +10 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/retConsStatServDCe_v1.00.xsd +10 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/tiposGeralDCe_v1.00.xsd +712 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/consulta/xmldsig-core-schema_v1.01.xsd +98 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/dceTiposBasico_v1.00.xsd +1410 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/dce_v1.00.xsd +10 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/evCancDCe_v1.00.xsd +36 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/eventoDCeTiposBasico_v1.00.xsd +283 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/eventoDCe_v1.00.xsd +9 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/procEventoDCe_v1.00.xsd +10 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/retEventoDCe_v1.00.xsd +9 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/tiposGeralDCe_v1.00.xsd +712 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/evento/xmldsig-core-schema_v1.01.xsd +98 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/procDCe_v1.00.xsd +37 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/retDCe_v1.00.xsd +9 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/tiposGeralDCe_v1.00.xsd +712 -0
- package/schemas/dce/PL_DCe_100a_NT2024.001/xmldsig-core-schema_v1.01.xsd +98 -0
- package/schemas/nfe/PL_009_V4/enviNFe_v3.10.xsd +8 -8
- package/schemas/nfe/PL_009_V4/xmldsig-core-schema_v1.01.xsd +97 -97
- package/scripts/download-schemas.js +39 -39
- package/scripts/test-xsd.js +34 -34
- package/src/api/server.js +316 -316
- package/src/constants/sefaz.js +69 -69
- package/src/danfe/DanfeService.js +205 -205
- package/src/danfe/xml-extract.js +69 -69
- package/src/dce/builders/DCeEventoXmlBuilder.js +86 -0
- package/src/dce/builders/DCeXmlBuilder.js +345 -0
- package/src/dce/constants/dce.js +87 -0
- package/src/dce/dace/DaceService.js +356 -0
- package/src/dce/dace/dace-extract.js +114 -0
- package/src/dce/services/DCeService.js +263 -0
- package/src/dce/services/DCeSoapService.js +235 -0
- package/src/dce/services/DCeXmlService.js +67 -0
- package/src/dce/types/DCeDocument.js +106 -0
- package/src/dce/utils/qrcode.utils.js +59 -0
- package/src/errors/GhinfeError.js +13 -13
- package/src/errors/SefazError.js +25 -25
- package/src/errors/XsdValidationError.js +15 -15
- package/src/index.js +84 -60
- package/src/nfce/builders/NFCeXmlBuilder.js +178 -178
- package/src/nfce/constants/qrcode.js +26 -26
- package/src/nfce/services/NFCeService.js +188 -188
- package/src/nfce/services/NFCeXmlService.js +38 -38
- package/src/nfce/types/NFCeDocument.js +42 -42
- package/src/nfce/utils/qrcode.utils.js +92 -92
- package/src/nfe/builders/NFeEventoXmlBuilder.js +110 -110
- package/src/nfe/builders/NFeXmlBuilder.js +215 -215
- package/src/nfe/mocks/sefaz-responses.js +195 -195
- package/src/nfe/services/NFeEventoService.js +95 -95
- package/src/nfe/services/NFeService.js +196 -196
- package/src/nfe/services/NFeSignService.js +127 -111
- package/src/nfe/services/NFeSoapService.js +437 -437
- package/src/nfe/services/NFeXmlService.js +41 -41
- package/src/nfe/services/NFeXsdService.js +56 -56
- package/src/nfe/types/NFeDocument.js +92 -92
- package/src/nfe/types/NFeEvento.js +44 -44
- package/src/nfse/NFSeMunicipioResolver.js +42 -42
- package/src/nfse/builders/NFSeEventoXmlBuilder.js +92 -92
- package/src/nfse/builders/NFSeXmlBuilder.js +16 -16
- package/src/nfse/constants/municipios.js +82 -82
- package/src/nfse/layouts/adapters.js +202 -202
- package/src/nfse/mocks/nfse-responses.js +142 -142
- package/src/nfse/services/NFSeService.js +191 -191
- package/src/nfse/services/NFSeSoapService.js +232 -232
- package/src/nfse/services/NFSeXmlService.js +12 -12
- package/src/nfse/types/NFSeDocument.js +54 -54
- package/src/queue/NFCeQueue.js +63 -63
- package/src/queue/NFSeQueue.js +59 -59
- package/src/queue/NFeQueue.js +76 -76
- package/src/reforma/ibscbs.js +175 -175
- package/src/sefaz/SefazEndpointResolver.js +95 -95
- package/src/sefaz/ca/icp-brasil-raiz-v10.pem +38 -0
- package/src/sefaz/endpoints.registry.js +205 -205
- package/src/sefaz/httpsAgent.js +33 -0
- package/src/shared/fiscal.helpers.js +53 -53
- package/src/utils/certificate.utils.js +69 -47
- package/src/utils/chave.utils.js +205 -117
- package/src/utils/code128.utils.js +67 -0
- package/src/utils/date.utils.js +26 -26
- package/src/utils/xml.utils.js +44 -44
- package/src/validation/XsdValidator.js +133 -114
- package/src/validation/schemas.js +18 -14
package/src/reforma/ibscbs.js
CHANGED
|
@@ -1,175 +1,175 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Constantes e helpers — Reforma Tributária (NT 2025.002 / PL_010).
|
|
3
|
-
* IBS + CBS. Injeção no builder NF-e/NFC-e quando item.reforma ou reformaTributaria.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export const REFORMA_LAYOUT = 'PL_010';
|
|
7
|
-
|
|
8
|
-
export const CST_IBSCBS = {
|
|
9
|
-
TRIBUTACAO_INTEGRAL: '000',
|
|
10
|
-
ISENCAO: '100',
|
|
11
|
-
DIFERIMENTO: '200',
|
|
12
|
-
REDUCAO_BASE: '300',
|
|
13
|
-
SUSPENSAO: '400',
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @typedef {Object} TributacaoRTC
|
|
18
|
-
* @property {string} [cst]
|
|
19
|
-
* @property {string} [cClassTrib]
|
|
20
|
-
* @property {number} [vBC]
|
|
21
|
-
* @property {number} [pIBSUF]
|
|
22
|
-
* @property {number} [pIBSMun]
|
|
23
|
-
* @property {number} [pCBS]
|
|
24
|
-
* @property {number} [vIBSUF]
|
|
25
|
-
* @property {number} [vIBSMun]
|
|
26
|
-
* @property {number} [vCBS]
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param {number} baseCalculo
|
|
31
|
-
* @param {Omit<TributacaoRTC, 'vIBSUF'|'vIBSMun'|'vCBS'|'vBC'>} [aliquotas]
|
|
32
|
-
* @returns {TributacaoRTC & { vBC: number }}
|
|
33
|
-
*/
|
|
34
|
-
export function calcularIBSCBS(baseCalculo, aliquotas = {}) {
|
|
35
|
-
const pIBSUF = aliquotas.pIBSUF ?? 0;
|
|
36
|
-
const pIBSMun = aliquotas.pIBSMun ?? 0;
|
|
37
|
-
const pCBS = aliquotas.pCBS ?? 0;
|
|
38
|
-
const base = Number(baseCalculo) || 0;
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
cst: aliquotas.cst ?? CST_IBSCBS.TRIBUTACAO_INTEGRAL,
|
|
42
|
-
cClassTrib: aliquotas.cClassTrib,
|
|
43
|
-
vBC: base,
|
|
44
|
-
pIBSUF,
|
|
45
|
-
pIBSMun,
|
|
46
|
-
pCBS,
|
|
47
|
-
vIBSUF: Number(((base * pIBSUF) / 100).toFixed(2)),
|
|
48
|
-
vIBSMun: Number(((base * pIBSMun) / 100).toFixed(2)),
|
|
49
|
-
vCBS: Number(((base * pCBS) / 100).toFixed(2)),
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* @param {TributacaoRTC} trib
|
|
55
|
-
* @returns {string}
|
|
56
|
-
*/
|
|
57
|
-
export function buildFragmentoIBSCBS(trib) {
|
|
58
|
-
const dec = (v, d = 2) => Number(v ?? 0).toFixed(d);
|
|
59
|
-
return `<IBSCBS>
|
|
60
|
-
<CST>${trib.cst ?? CST_IBSCBS.TRIBUTACAO_INTEGRAL}</CST>
|
|
61
|
-
${trib.cClassTrib ? `<cClassTrib>${trib.cClassTrib}</cClassTrib>` : ''}
|
|
62
|
-
<gIBSCBS>
|
|
63
|
-
<vBC>${dec(trib.vBC ?? 0)}</vBC>
|
|
64
|
-
<gIBSUF>
|
|
65
|
-
<pIBSUF>${dec(trib.pIBSUF, 4)}</pIBSUF>
|
|
66
|
-
<vIBSUF>${dec(trib.vIBSUF)}</vIBSUF>
|
|
67
|
-
</gIBSUF>
|
|
68
|
-
<gIBSMun>
|
|
69
|
-
<pIBSMun>${dec(trib.pIBSMun, 4)}</pIBSMun>
|
|
70
|
-
<vIBSMun>${dec(trib.vIBSMun)}</vIBSMun>
|
|
71
|
-
</gIBSMun>
|
|
72
|
-
<gCBS>
|
|
73
|
-
<pCBS>${dec(trib.pCBS, 4)}</pCBS>
|
|
74
|
-
<vCBS>${dec(trib.vCBS)}</vCBS>
|
|
75
|
-
</gCBS>
|
|
76
|
-
</gIBSCBS>
|
|
77
|
-
</IBSCBS>`;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Anexa grupo IBSCBS ao nó imposto (xmlbuilder2).
|
|
82
|
-
* @param {import('xmlbuilder2').XMLBuilder} impostoNode
|
|
83
|
-
* @param {TributacaoRTC} trib
|
|
84
|
-
*/
|
|
85
|
-
export function appendIBSCBS(impostoNode, trib) {
|
|
86
|
-
if (!trib) return;
|
|
87
|
-
const dec = (v, d = 2) => Number(v ?? 0).toFixed(d);
|
|
88
|
-
const ibs = impostoNode.ele('IBSCBS');
|
|
89
|
-
ibs.ele('CST').txt(trib.cst ?? CST_IBSCBS.TRIBUTACAO_INTEGRAL).up();
|
|
90
|
-
if (trib.cClassTrib) ibs.ele('cClassTrib').txt(trib.cClassTrib).up();
|
|
91
|
-
|
|
92
|
-
const g = ibs.ele('gIBSCBS');
|
|
93
|
-
g.ele('vBC').txt(dec(trib.vBC ?? 0)).up();
|
|
94
|
-
|
|
95
|
-
const gUf = g.ele('gIBSUF');
|
|
96
|
-
gUf.ele('pIBSUF').txt(dec(trib.pIBSUF, 4)).up();
|
|
97
|
-
gUf.ele('vIBSUF').txt(dec(trib.vIBSUF)).up();
|
|
98
|
-
gUf.up();
|
|
99
|
-
|
|
100
|
-
const gMun = g.ele('gIBSMun');
|
|
101
|
-
gMun.ele('pIBSMun').txt(dec(trib.pIBSMun, 4)).up();
|
|
102
|
-
gMun.ele('vIBSMun').txt(dec(trib.vIBSMun)).up();
|
|
103
|
-
gMun.up();
|
|
104
|
-
|
|
105
|
-
const gCbs = g.ele('gCBS');
|
|
106
|
-
gCbs.ele('pCBS').txt(dec(trib.pCBS, 4)).up();
|
|
107
|
-
gCbs.ele('vCBS').txt(dec(trib.vCBS)).up();
|
|
108
|
-
gCbs.up();
|
|
109
|
-
|
|
110
|
-
g.up();
|
|
111
|
-
ibs.up();
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Anexa totais IBS/CBS em <total> (irmão de ICMSTot).
|
|
116
|
-
* @param {import('xmlbuilder2').XMLBuilder} totalParent
|
|
117
|
-
* @param {{ vIBSUF: number, vIBSMun: number, vCBS: number }} totais
|
|
118
|
-
*/
|
|
119
|
-
export function appendTotaisIBSCBS(totalParent, totais) {
|
|
120
|
-
if (!totais) return;
|
|
121
|
-
const dec = (v) => Number(v ?? 0).toFixed(2);
|
|
122
|
-
const node = totalParent.ele('IBSCBSTot');
|
|
123
|
-
node.ele('vIBS').txt(dec((totais.vIBSUF ?? 0) + (totais.vIBSMun ?? 0))).up();
|
|
124
|
-
node.ele('vIBSUF').txt(dec(totais.vIBSUF)).up();
|
|
125
|
-
node.ele('vIBSMun').txt(dec(totais.vIBSMun)).up();
|
|
126
|
-
node.ele('vCBS').txt(dec(totais.vCBS)).up();
|
|
127
|
-
node.up();
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* @param {Array<{ reforma?: TributacaoRTC, valorTotal?: number }>} itens
|
|
132
|
-
* @param {boolean} [autoCalcular]
|
|
133
|
-
*/
|
|
134
|
-
export function normalizarItensReforma(itens = [], autoCalcular = false) {
|
|
135
|
-
return itens.map((item) => {
|
|
136
|
-
if (item.reforma) {
|
|
137
|
-
if (item.reforma.vIBSUF == null && autoCalcular !== false) {
|
|
138
|
-
return {
|
|
139
|
-
...item,
|
|
140
|
-
reforma: calcularIBSCBS(item.reforma.vBC ?? item.valorTotal ?? 0, item.reforma),
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
return item;
|
|
144
|
-
}
|
|
145
|
-
return item;
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* @param {Array<{ reforma?: TributacaoRTC }>} itens
|
|
151
|
-
*/
|
|
152
|
-
export function somarTotaisReforma(itens = []) {
|
|
153
|
-
return itens.reduce(
|
|
154
|
-
(acc, item) => {
|
|
155
|
-
const r = item.reforma;
|
|
156
|
-
if (!r) return acc;
|
|
157
|
-
acc.vIBSUF += r.vIBSUF ?? 0;
|
|
158
|
-
acc.vIBSMun += r.vIBSMun ?? 0;
|
|
159
|
-
acc.vCBS += r.vCBS ?? 0;
|
|
160
|
-
return acc;
|
|
161
|
-
},
|
|
162
|
-
{ vIBSUF: 0, vIBSMun: 0, vCBS: 0 }
|
|
163
|
-
);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* @param {{ reformaTributaria?: boolean, itens?: Array<{ reforma?: unknown }> }} documentoOuOptions
|
|
168
|
-
*/
|
|
169
|
-
export function reformaHabilitada(documentoOuOptions = {}) {
|
|
170
|
-
if (documentoOuOptions.reformaTributaria) return true;
|
|
171
|
-
if (Array.isArray(documentoOuOptions.itens)) {
|
|
172
|
-
return documentoOuOptions.itens.some((i) => i.reforma);
|
|
173
|
-
}
|
|
174
|
-
return false;
|
|
175
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Constantes e helpers — Reforma Tributária (NT 2025.002 / PL_010).
|
|
3
|
+
* IBS + CBS. Injeção no builder NF-e/NFC-e quando item.reforma ou reformaTributaria.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const REFORMA_LAYOUT = 'PL_010';
|
|
7
|
+
|
|
8
|
+
export const CST_IBSCBS = {
|
|
9
|
+
TRIBUTACAO_INTEGRAL: '000',
|
|
10
|
+
ISENCAO: '100',
|
|
11
|
+
DIFERIMENTO: '200',
|
|
12
|
+
REDUCAO_BASE: '300',
|
|
13
|
+
SUSPENSAO: '400',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {Object} TributacaoRTC
|
|
18
|
+
* @property {string} [cst]
|
|
19
|
+
* @property {string} [cClassTrib]
|
|
20
|
+
* @property {number} [vBC]
|
|
21
|
+
* @property {number} [pIBSUF]
|
|
22
|
+
* @property {number} [pIBSMun]
|
|
23
|
+
* @property {number} [pCBS]
|
|
24
|
+
* @property {number} [vIBSUF]
|
|
25
|
+
* @property {number} [vIBSMun]
|
|
26
|
+
* @property {number} [vCBS]
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {number} baseCalculo
|
|
31
|
+
* @param {Omit<TributacaoRTC, 'vIBSUF'|'vIBSMun'|'vCBS'|'vBC'>} [aliquotas]
|
|
32
|
+
* @returns {TributacaoRTC & { vBC: number }}
|
|
33
|
+
*/
|
|
34
|
+
export function calcularIBSCBS(baseCalculo, aliquotas = {}) {
|
|
35
|
+
const pIBSUF = aliquotas.pIBSUF ?? 0;
|
|
36
|
+
const pIBSMun = aliquotas.pIBSMun ?? 0;
|
|
37
|
+
const pCBS = aliquotas.pCBS ?? 0;
|
|
38
|
+
const base = Number(baseCalculo) || 0;
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
cst: aliquotas.cst ?? CST_IBSCBS.TRIBUTACAO_INTEGRAL,
|
|
42
|
+
cClassTrib: aliquotas.cClassTrib,
|
|
43
|
+
vBC: base,
|
|
44
|
+
pIBSUF,
|
|
45
|
+
pIBSMun,
|
|
46
|
+
pCBS,
|
|
47
|
+
vIBSUF: Number(((base * pIBSUF) / 100).toFixed(2)),
|
|
48
|
+
vIBSMun: Number(((base * pIBSMun) / 100).toFixed(2)),
|
|
49
|
+
vCBS: Number(((base * pCBS) / 100).toFixed(2)),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {TributacaoRTC} trib
|
|
55
|
+
* @returns {string}
|
|
56
|
+
*/
|
|
57
|
+
export function buildFragmentoIBSCBS(trib) {
|
|
58
|
+
const dec = (v, d = 2) => Number(v ?? 0).toFixed(d);
|
|
59
|
+
return `<IBSCBS>
|
|
60
|
+
<CST>${trib.cst ?? CST_IBSCBS.TRIBUTACAO_INTEGRAL}</CST>
|
|
61
|
+
${trib.cClassTrib ? `<cClassTrib>${trib.cClassTrib}</cClassTrib>` : ''}
|
|
62
|
+
<gIBSCBS>
|
|
63
|
+
<vBC>${dec(trib.vBC ?? 0)}</vBC>
|
|
64
|
+
<gIBSUF>
|
|
65
|
+
<pIBSUF>${dec(trib.pIBSUF, 4)}</pIBSUF>
|
|
66
|
+
<vIBSUF>${dec(trib.vIBSUF)}</vIBSUF>
|
|
67
|
+
</gIBSUF>
|
|
68
|
+
<gIBSMun>
|
|
69
|
+
<pIBSMun>${dec(trib.pIBSMun, 4)}</pIBSMun>
|
|
70
|
+
<vIBSMun>${dec(trib.vIBSMun)}</vIBSMun>
|
|
71
|
+
</gIBSMun>
|
|
72
|
+
<gCBS>
|
|
73
|
+
<pCBS>${dec(trib.pCBS, 4)}</pCBS>
|
|
74
|
+
<vCBS>${dec(trib.vCBS)}</vCBS>
|
|
75
|
+
</gCBS>
|
|
76
|
+
</gIBSCBS>
|
|
77
|
+
</IBSCBS>`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Anexa grupo IBSCBS ao nó imposto (xmlbuilder2).
|
|
82
|
+
* @param {import('xmlbuilder2').XMLBuilder} impostoNode
|
|
83
|
+
* @param {TributacaoRTC} trib
|
|
84
|
+
*/
|
|
85
|
+
export function appendIBSCBS(impostoNode, trib) {
|
|
86
|
+
if (!trib) return;
|
|
87
|
+
const dec = (v, d = 2) => Number(v ?? 0).toFixed(d);
|
|
88
|
+
const ibs = impostoNode.ele('IBSCBS');
|
|
89
|
+
ibs.ele('CST').txt(trib.cst ?? CST_IBSCBS.TRIBUTACAO_INTEGRAL).up();
|
|
90
|
+
if (trib.cClassTrib) ibs.ele('cClassTrib').txt(trib.cClassTrib).up();
|
|
91
|
+
|
|
92
|
+
const g = ibs.ele('gIBSCBS');
|
|
93
|
+
g.ele('vBC').txt(dec(trib.vBC ?? 0)).up();
|
|
94
|
+
|
|
95
|
+
const gUf = g.ele('gIBSUF');
|
|
96
|
+
gUf.ele('pIBSUF').txt(dec(trib.pIBSUF, 4)).up();
|
|
97
|
+
gUf.ele('vIBSUF').txt(dec(trib.vIBSUF)).up();
|
|
98
|
+
gUf.up();
|
|
99
|
+
|
|
100
|
+
const gMun = g.ele('gIBSMun');
|
|
101
|
+
gMun.ele('pIBSMun').txt(dec(trib.pIBSMun, 4)).up();
|
|
102
|
+
gMun.ele('vIBSMun').txt(dec(trib.vIBSMun)).up();
|
|
103
|
+
gMun.up();
|
|
104
|
+
|
|
105
|
+
const gCbs = g.ele('gCBS');
|
|
106
|
+
gCbs.ele('pCBS').txt(dec(trib.pCBS, 4)).up();
|
|
107
|
+
gCbs.ele('vCBS').txt(dec(trib.vCBS)).up();
|
|
108
|
+
gCbs.up();
|
|
109
|
+
|
|
110
|
+
g.up();
|
|
111
|
+
ibs.up();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Anexa totais IBS/CBS em <total> (irmão de ICMSTot).
|
|
116
|
+
* @param {import('xmlbuilder2').XMLBuilder} totalParent
|
|
117
|
+
* @param {{ vIBSUF: number, vIBSMun: number, vCBS: number }} totais
|
|
118
|
+
*/
|
|
119
|
+
export function appendTotaisIBSCBS(totalParent, totais) {
|
|
120
|
+
if (!totais) return;
|
|
121
|
+
const dec = (v) => Number(v ?? 0).toFixed(2);
|
|
122
|
+
const node = totalParent.ele('IBSCBSTot');
|
|
123
|
+
node.ele('vIBS').txt(dec((totais.vIBSUF ?? 0) + (totais.vIBSMun ?? 0))).up();
|
|
124
|
+
node.ele('vIBSUF').txt(dec(totais.vIBSUF)).up();
|
|
125
|
+
node.ele('vIBSMun').txt(dec(totais.vIBSMun)).up();
|
|
126
|
+
node.ele('vCBS').txt(dec(totais.vCBS)).up();
|
|
127
|
+
node.up();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @param {Array<{ reforma?: TributacaoRTC, valorTotal?: number }>} itens
|
|
132
|
+
* @param {boolean} [autoCalcular]
|
|
133
|
+
*/
|
|
134
|
+
export function normalizarItensReforma(itens = [], autoCalcular = false) {
|
|
135
|
+
return itens.map((item) => {
|
|
136
|
+
if (item.reforma) {
|
|
137
|
+
if (item.reforma.vIBSUF == null && autoCalcular !== false) {
|
|
138
|
+
return {
|
|
139
|
+
...item,
|
|
140
|
+
reforma: calcularIBSCBS(item.reforma.vBC ?? item.valorTotal ?? 0, item.reforma),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
return item;
|
|
144
|
+
}
|
|
145
|
+
return item;
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @param {Array<{ reforma?: TributacaoRTC }>} itens
|
|
151
|
+
*/
|
|
152
|
+
export function somarTotaisReforma(itens = []) {
|
|
153
|
+
return itens.reduce(
|
|
154
|
+
(acc, item) => {
|
|
155
|
+
const r = item.reforma;
|
|
156
|
+
if (!r) return acc;
|
|
157
|
+
acc.vIBSUF += r.vIBSUF ?? 0;
|
|
158
|
+
acc.vIBSMun += r.vIBSMun ?? 0;
|
|
159
|
+
acc.vCBS += r.vCBS ?? 0;
|
|
160
|
+
return acc;
|
|
161
|
+
},
|
|
162
|
+
{ vIBSUF: 0, vIBSMun: 0, vCBS: 0 }
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @param {{ reformaTributaria?: boolean, itens?: Array<{ reforma?: unknown }> }} documentoOuOptions
|
|
168
|
+
*/
|
|
169
|
+
export function reformaHabilitada(documentoOuOptions = {}) {
|
|
170
|
+
if (documentoOuOptions.reformaTributaria) return true;
|
|
171
|
+
if (Array.isArray(documentoOuOptions.itens)) {
|
|
172
|
+
return documentoOuOptions.itens.some((i) => i.reforma);
|
|
173
|
+
}
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
@@ -1,95 +1,95 @@
|
|
|
1
|
-
import { UF_AUTORIZADOR, AUTORIZADOR_ENDPOINTS, SEFAZ_SERVICO } from './endpoints.registry.js';
|
|
2
|
-
import { GhinfeError } from '../errors/GhinfeError.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Resolve endpoints SEFAZ por UF, ambiente e tipo de serviço.
|
|
6
|
-
* Elimina necessidade de configurar URLs manualmente em produção.
|
|
7
|
-
*/
|
|
8
|
-
export class SefazEndpointResolver {
|
|
9
|
-
/**
|
|
10
|
-
* @param {string} uf Sigla da UF (ex: "SP")
|
|
11
|
-
* @returns {string} Código do autorizador (ex: "SVRS", "SP")
|
|
12
|
-
*/
|
|
13
|
-
static obterAutorizador(uf) {
|
|
14
|
-
const autorizador = UF_AUTORIZADOR[uf?.toUpperCase()];
|
|
15
|
-
if (!autorizador) {
|
|
16
|
-
throw new GhinfeError(`UF não mapeada para autorizador SEFAZ: ${uf}`, 'UF_AUTORIZADOR_NOT_FOUND');
|
|
17
|
-
}
|
|
18
|
-
return autorizador;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param {string} uf
|
|
23
|
-
* @param {number} [ambiente] 1=Produção, 2=Homologação
|
|
24
|
-
* @returns {Record<string, string>}
|
|
25
|
-
*/
|
|
26
|
-
static obterEndpoints(uf, ambiente = 2) {
|
|
27
|
-
const autorizador = this.obterAutorizador(uf);
|
|
28
|
-
const endpoints = AUTORIZADOR_ENDPOINTS[autorizador]?.[ambiente];
|
|
29
|
-
|
|
30
|
-
if (!endpoints) {
|
|
31
|
-
throw new GhinfeError(
|
|
32
|
-
`Endpoints não configurados para autorizador ${autorizador} ambiente ${ambiente}`,
|
|
33
|
-
'SEFAZ_ENDPOINTS_NOT_FOUND'
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return { autorizador, ambiente, endpoints };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @param {{
|
|
42
|
-
* uf: string,
|
|
43
|
-
* ambiente?: number,
|
|
44
|
-
* servico?: string,
|
|
45
|
-
* modelo?: '55'|'65',
|
|
46
|
-
* }} params
|
|
47
|
-
* @returns {string}
|
|
48
|
-
*/
|
|
49
|
-
static resolver(params) {
|
|
50
|
-
const { endpoints } = this.obterEndpoints(params.uf, params.ambiente ?? 2);
|
|
51
|
-
const servico = params.servico ?? SEFAZ_SERVICO.AUTORIZACAO;
|
|
52
|
-
const url = endpoints[servico];
|
|
53
|
-
|
|
54
|
-
if (!url) {
|
|
55
|
-
throw new GhinfeError(
|
|
56
|
-
`Serviço "${servico}" não disponível para UF ${params.uf} (autorizador ${this.obterAutorizador(params.uf)})`,
|
|
57
|
-
'SEFAZ_SERVICO_NOT_FOUND',
|
|
58
|
-
{ servico, uf: params.uf, modelo: params.modelo }
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return url;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Configuração pronta para NFeSoapService.
|
|
67
|
-
* @param {string} uf
|
|
68
|
-
* @param {number} [ambiente]
|
|
69
|
-
*/
|
|
70
|
-
static paraNFe(uf, ambiente = 2) {
|
|
71
|
-
return {
|
|
72
|
-
endpoint: this.resolver({ uf, ambiente, servico: SEFAZ_SERVICO.AUTORIZACAO, modelo: '55' }),
|
|
73
|
-
eventoEndpoint: this.resolver({ uf, ambiente, servico: SEFAZ_SERVICO.EVENTO, modelo: '55' }),
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* NFC-e usa os mesmos webservices de autorização na maioria dos estados.
|
|
79
|
-
* @param {string} uf
|
|
80
|
-
* @param {number} [ambiente]
|
|
81
|
-
*/
|
|
82
|
-
static paraNFCe(uf, ambiente = 2) {
|
|
83
|
-
return {
|
|
84
|
-
endpoint: this.resolver({ uf, ambiente, servico: SEFAZ_SERVICO.AUTORIZACAO, modelo: '65' }),
|
|
85
|
-
eventoEndpoint: this.resolver({ uf, ambiente, servico: SEFAZ_SERVICO.EVENTO, modelo: '65' }),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/** @returns {string[]} */
|
|
90
|
-
static listarUFs() {
|
|
91
|
-
return Object.keys(UF_AUTORIZADOR);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export { SEFAZ_SERVICO };
|
|
1
|
+
import { UF_AUTORIZADOR, AUTORIZADOR_ENDPOINTS, SEFAZ_SERVICO } from './endpoints.registry.js';
|
|
2
|
+
import { GhinfeError } from '../errors/GhinfeError.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Resolve endpoints SEFAZ por UF, ambiente e tipo de serviço.
|
|
6
|
+
* Elimina necessidade de configurar URLs manualmente em produção.
|
|
7
|
+
*/
|
|
8
|
+
export class SefazEndpointResolver {
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} uf Sigla da UF (ex: "SP")
|
|
11
|
+
* @returns {string} Código do autorizador (ex: "SVRS", "SP")
|
|
12
|
+
*/
|
|
13
|
+
static obterAutorizador(uf) {
|
|
14
|
+
const autorizador = UF_AUTORIZADOR[uf?.toUpperCase()];
|
|
15
|
+
if (!autorizador) {
|
|
16
|
+
throw new GhinfeError(`UF não mapeada para autorizador SEFAZ: ${uf}`, 'UF_AUTORIZADOR_NOT_FOUND');
|
|
17
|
+
}
|
|
18
|
+
return autorizador;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} uf
|
|
23
|
+
* @param {number} [ambiente] 1=Produção, 2=Homologação
|
|
24
|
+
* @returns {Record<string, string>}
|
|
25
|
+
*/
|
|
26
|
+
static obterEndpoints(uf, ambiente = 2) {
|
|
27
|
+
const autorizador = this.obterAutorizador(uf);
|
|
28
|
+
const endpoints = AUTORIZADOR_ENDPOINTS[autorizador]?.[ambiente];
|
|
29
|
+
|
|
30
|
+
if (!endpoints) {
|
|
31
|
+
throw new GhinfeError(
|
|
32
|
+
`Endpoints não configurados para autorizador ${autorizador} ambiente ${ambiente}`,
|
|
33
|
+
'SEFAZ_ENDPOINTS_NOT_FOUND'
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return { autorizador, ambiente, endpoints };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {{
|
|
42
|
+
* uf: string,
|
|
43
|
+
* ambiente?: number,
|
|
44
|
+
* servico?: string,
|
|
45
|
+
* modelo?: '55'|'65',
|
|
46
|
+
* }} params
|
|
47
|
+
* @returns {string}
|
|
48
|
+
*/
|
|
49
|
+
static resolver(params) {
|
|
50
|
+
const { endpoints } = this.obterEndpoints(params.uf, params.ambiente ?? 2);
|
|
51
|
+
const servico = params.servico ?? SEFAZ_SERVICO.AUTORIZACAO;
|
|
52
|
+
const url = endpoints[servico];
|
|
53
|
+
|
|
54
|
+
if (!url) {
|
|
55
|
+
throw new GhinfeError(
|
|
56
|
+
`Serviço "${servico}" não disponível para UF ${params.uf} (autorizador ${this.obterAutorizador(params.uf)})`,
|
|
57
|
+
'SEFAZ_SERVICO_NOT_FOUND',
|
|
58
|
+
{ servico, uf: params.uf, modelo: params.modelo }
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return url;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Configuração pronta para NFeSoapService.
|
|
67
|
+
* @param {string} uf
|
|
68
|
+
* @param {number} [ambiente]
|
|
69
|
+
*/
|
|
70
|
+
static paraNFe(uf, ambiente = 2) {
|
|
71
|
+
return {
|
|
72
|
+
endpoint: this.resolver({ uf, ambiente, servico: SEFAZ_SERVICO.AUTORIZACAO, modelo: '55' }),
|
|
73
|
+
eventoEndpoint: this.resolver({ uf, ambiente, servico: SEFAZ_SERVICO.EVENTO, modelo: '55' }),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* NFC-e usa os mesmos webservices de autorização na maioria dos estados.
|
|
79
|
+
* @param {string} uf
|
|
80
|
+
* @param {number} [ambiente]
|
|
81
|
+
*/
|
|
82
|
+
static paraNFCe(uf, ambiente = 2) {
|
|
83
|
+
return {
|
|
84
|
+
endpoint: this.resolver({ uf, ambiente, servico: SEFAZ_SERVICO.AUTORIZACAO, modelo: '65' }),
|
|
85
|
+
eventoEndpoint: this.resolver({ uf, ambiente, servico: SEFAZ_SERVICO.EVENTO, modelo: '65' }),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** @returns {string[]} */
|
|
90
|
+
static listarUFs() {
|
|
91
|
+
return Object.keys(UF_AUTORIZADOR);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { SEFAZ_SERVICO };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIGrDCCBJSgAwIBAgIJANLVi0S/gZNCMA0GCSqGSIb3DQEBDQUAMIGYMQswCQYD
|
|
3
|
+
VQQGEwJCUjETMBEGA1UECgwKSUNQLUJyYXNpbDE9MDsGA1UECww0SW5zdGl0dXRv
|
|
4
|
+
IE5hY2lvbmFsIGRlIFRlY25vbG9naWEgZGEgSW5mb3JtYWNhbyAtIElUSTE1MDMG
|
|
5
|
+
A1UEAwwsQXV0b3JpZGFkZSBDZXJ0aWZpY2Fkb3JhIFJhaXogQnJhc2lsZWlyYSB2
|
|
6
|
+
MTAwHhcNMTkwNzAxMTkxNTU5WhcNMzIwNzAxMTIwMDU5WjCBmDELMAkGA1UEBhMC
|
|
7
|
+
QlIxEzARBgNVBAoMCklDUC1CcmFzaWwxPTA7BgNVBAsMNEluc3RpdHV0byBOYWNp
|
|
8
|
+
b25hbCBkZSBUZWNub2xvZ2lhIGRhIEluZm9ybWFjYW8gLSBJVEkxNTAzBgNVBAMM
|
|
9
|
+
LEF1dG9yaWRhZGUgQ2VydGlmaWNhZG9yYSBSYWl6IEJyYXNpbGVpcmEgdjEwMIIC
|
|
10
|
+
IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAk3AxKl1ZtP0pNyjChqO7qNkn
|
|
11
|
+
+/sClZeqiV/Kd7KnnbkDbI2y3VWcUG7feCE/deIxot6GH6JXncRG794UZl+4doD0
|
|
12
|
+
D0/cEwBd4DvrDSZm0RT40xhmYYOTxZDJxv+coTHdmsT5aNmSkktfjzYX4HQHh/7M
|
|
13
|
+
em+kTOpT/3E4K6B7KVs9HkOT7nXx5yU1qYbVWqI0qpJM9mOTSFx8C9HiKcHvLCvt
|
|
14
|
+
1ioXKPAmFuHPkayOcXP2MXeb+VRNjWKU4E+L2t5uZPKVx1M/9i1DztlLb4K8OfYg
|
|
15
|
+
GaPDUSF1sxnoGk5qZHLleO6KjCpmuQepmgsBvxi2YNO7X2YUwQQx1AXNSolgtkAR
|
|
16
|
+
5gt+1WzxhbFUhItQqlhqxgWHefLmiT5T/Ctz/P2v+zSO4efkkIzsi1iwD+ypZvM2
|
|
17
|
+
lnIvB24RcSN6jzmCahLPX4CwjwIK6JsSoMVxIhpZHCguUP4LXqP8IWUZ6WgS/4zB
|
|
18
|
+
7B9E0EICl2rM1PRy+6ulv+ZOW256e8a0pijUB+hXM1msUq9L92476FAAX8va3sP7
|
|
19
|
+
+Uut94+bGHmubcTLImWUPrxNT7QyrvE3FyHicfiHioeFL2oV4cXTLZrEq2wS8R4P
|
|
20
|
+
KPdSzNn5Z9e2uMEGYQaSNO+OwvVycpIhOBOqrm12wJ9ZhWKtM5UOo34/o37r5ZBI
|
|
21
|
+
TYXAGbhqQDB9mWXwH+0CAwEAAaOB9jCB8zBOBgNVHSAERzBFMEMGBWBMAQEAMDow
|
|
22
|
+
OAYIKwYBBQUHAgEWLGh0dHA6Ly9hY3JhaXouaWNwYnJhc2lsLmdvdi5ici9EUENh
|
|
23
|
+
Y3JhaXoucGRmMEAGA1UdHwQ5MDcwNaAzoDGGL2h0dHA6Ly9hY3JhaXouaWNwYnJh
|
|
24
|
+
c2lsLmdvdi5ici9MQ1JhY3JhaXp2MTAuY3JsMB8GA1UdIwQYMBaAFHTzfv/8n1N6
|
|
25
|
+
8Xzrqz6kptoYukVjMB0GA1UdDgQWBBR0837//J9TevF866s+pKbaGLpFYzAPBgNV
|
|
26
|
+
HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQ0FAAOCAgEA
|
|
27
|
+
eCNhBSuy/Ih/T+1VOtAJju85SrtoE3vET1qXASpmjQllDHG/ph7VFNRAkC+gha+B
|
|
28
|
+
CbjoA5oJ/8wwl+Qdp1KGz6nXXFTLx3osU+kjm0srmBf9nyXHPqvFyvBeB0A7sYb7
|
|
29
|
+
TmII9GKD20oCxsdkccR/oE/JuTaNnGq0GYZ2aDb5v62uLi21Y6P9UBiTxZqQ4ojW
|
|
30
|
+
ET6kXNjlK238jpXv17FR8Sg3VusCvX7Q8eJkavvHHZDeWck2fSA+ycAc2JeL2Z0B
|
|
31
|
+
MSxGWpH32WM9J8+6XqCJUXHiWEV0zCE8wDYiYC+047pTxQI/gB/FcU7jvylh98DJ
|
|
32
|
+
kQPHd/Tp6Og3ynlDA9n9uBbxYHVRZs9vsZ/7xTFaxRe+zk8dhgKgZ/3RrcMFB570
|
|
33
|
+
2t8LFbyuUE/kQVY6rZ0QJ9qMWQ7VPLRwRhiMeU3k8WDJb/tBbOXHBqldTbWyQ+mp
|
|
34
|
+
MEDWhbrzE/IED82wAuO23Tb05cYk2xC7+Izef8fSc3XdJDuPSbcDpWukzyCDtSEH
|
|
35
|
+
isLiGEtIbYRiPsF3czlQPsnIEVoTTCWxHCH1zYR6zScSv18Qh69qVe2J40K5jZoP
|
|
36
|
+
GEOhq/oKhVJQAdvAFW5Odp7mF3Tk9nivjjsctJSxY26LFiV5GRV+07SSse4ti0aO
|
|
37
|
+
jO5PLg5SWjfcOtBG2rz02EIvQAmLcb0kGBtfdj0lW/w=
|
|
38
|
+
-----END CERTIFICATE-----
|