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/queue/NFCeQueue.js
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
import Bull from 'bull';
|
|
2
|
-
import { NFCeService } from '../nfce/services/NFCeService.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Fila Bull/Redis para processamento assíncrono de NFC-e.
|
|
6
|
-
*/
|
|
7
|
-
export class NFCeQueue {
|
|
8
|
-
/**
|
|
9
|
-
* @param {{
|
|
10
|
-
* redis?: { host?: string, port?: number, password?: string },
|
|
11
|
-
* queueName?: string,
|
|
12
|
-
* nfceOptions?: ConstructorParameters<typeof NFCeService>[0],
|
|
13
|
-
* }} [options]
|
|
14
|
-
*/
|
|
15
|
-
constructor(options = {}) {
|
|
16
|
-
const redis = options.redis ?? { host: '127.0.0.1', port: 6379 };
|
|
17
|
-
const queueName = options.queueName ?? 'ghinfe:nfce:emissao';
|
|
18
|
-
|
|
19
|
-
this.queue = new Bull(queueName, { redis });
|
|
20
|
-
this.nfceService = new NFCeService(options.nfceOptions ?? { mock: true });
|
|
21
|
-
this.#registerProcessor();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
#registerProcessor() {
|
|
25
|
-
this.queue.process(async (job) => {
|
|
26
|
-
const { documento, certificado } = job.data;
|
|
27
|
-
return this.nfceService.emitir(documento, certificado);
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @param {{
|
|
33
|
-
* documento: import('../nfce/types/NFCeDocument.js').NFCeDocumento,
|
|
34
|
-
* certificado: { pfx: Buffer|string, senha: string },
|
|
35
|
-
* }} payload
|
|
36
|
-
*/
|
|
37
|
-
async adicionarEmissao(payload) {
|
|
38
|
-
return this.queue.add(payload, {
|
|
39
|
-
attempts: 3,
|
|
40
|
-
backoff: { type: 'exponential', delay: 5000 },
|
|
41
|
-
removeOnComplete: 100,
|
|
42
|
-
removeOnFail: 500,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** @param {(resultado: Awaited<ReturnType<NFCeService['emitir']>>, job: Bull.Job) => Promise<void>} handler */
|
|
47
|
-
onCompleted(handler) {
|
|
48
|
-
this.queue.on('completed', async (job, resultado) => {
|
|
49
|
-
await handler(resultado, job);
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** @param {(error: Error, job: Bull.Job) => Promise<void>} handler */
|
|
54
|
-
onFailed(handler) {
|
|
55
|
-
this.queue.on('failed', async (job, error) => {
|
|
56
|
-
await handler(error, job);
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async close() {
|
|
61
|
-
await this.queue.close();
|
|
62
|
-
}
|
|
63
|
-
}
|
|
1
|
+
import Bull from 'bull';
|
|
2
|
+
import { NFCeService } from '../nfce/services/NFCeService.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fila Bull/Redis para processamento assíncrono de NFC-e.
|
|
6
|
+
*/
|
|
7
|
+
export class NFCeQueue {
|
|
8
|
+
/**
|
|
9
|
+
* @param {{
|
|
10
|
+
* redis?: { host?: string, port?: number, password?: string },
|
|
11
|
+
* queueName?: string,
|
|
12
|
+
* nfceOptions?: ConstructorParameters<typeof NFCeService>[0],
|
|
13
|
+
* }} [options]
|
|
14
|
+
*/
|
|
15
|
+
constructor(options = {}) {
|
|
16
|
+
const redis = options.redis ?? { host: '127.0.0.1', port: 6379 };
|
|
17
|
+
const queueName = options.queueName ?? 'ghinfe:nfce:emissao';
|
|
18
|
+
|
|
19
|
+
this.queue = new Bull(queueName, { redis });
|
|
20
|
+
this.nfceService = new NFCeService(options.nfceOptions ?? { mock: true });
|
|
21
|
+
this.#registerProcessor();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#registerProcessor() {
|
|
25
|
+
this.queue.process(async (job) => {
|
|
26
|
+
const { documento, certificado } = job.data;
|
|
27
|
+
return this.nfceService.emitir(documento, certificado);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {{
|
|
33
|
+
* documento: import('../nfce/types/NFCeDocument.js').NFCeDocumento,
|
|
34
|
+
* certificado: { pfx: Buffer|string, senha: string },
|
|
35
|
+
* }} payload
|
|
36
|
+
*/
|
|
37
|
+
async adicionarEmissao(payload) {
|
|
38
|
+
return this.queue.add(payload, {
|
|
39
|
+
attempts: 3,
|
|
40
|
+
backoff: { type: 'exponential', delay: 5000 },
|
|
41
|
+
removeOnComplete: 100,
|
|
42
|
+
removeOnFail: 500,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** @param {(resultado: Awaited<ReturnType<NFCeService['emitir']>>, job: Bull.Job) => Promise<void>} handler */
|
|
47
|
+
onCompleted(handler) {
|
|
48
|
+
this.queue.on('completed', async (job, resultado) => {
|
|
49
|
+
await handler(resultado, job);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** @param {(error: Error, job: Bull.Job) => Promise<void>} handler */
|
|
54
|
+
onFailed(handler) {
|
|
55
|
+
this.queue.on('failed', async (job, error) => {
|
|
56
|
+
await handler(error, job);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async close() {
|
|
61
|
+
await this.queue.close();
|
|
62
|
+
}
|
|
63
|
+
}
|
package/src/queue/NFSeQueue.js
CHANGED
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
import Bull from 'bull';
|
|
2
|
-
import { NFSeService } from '../nfse/services/NFSeService.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Fila Bull/Redis para processamento assíncrono de NFS-e.
|
|
6
|
-
*/
|
|
7
|
-
export class NFSeQueue {
|
|
8
|
-
/**
|
|
9
|
-
* @param {{
|
|
10
|
-
* redis?: { host?: string, port?: number, password?: string },
|
|
11
|
-
* queueName?: string,
|
|
12
|
-
* nfseOptions?: ConstructorParameters<typeof NFSeService>[0],
|
|
13
|
-
* }} [options]
|
|
14
|
-
*/
|
|
15
|
-
constructor(options = {}) {
|
|
16
|
-
const redis = options.redis ?? { host: '127.0.0.1', port: 6379 };
|
|
17
|
-
const queueName = options.queueName ?? 'ghinfe:nfse:emissao';
|
|
18
|
-
|
|
19
|
-
this.queue = new Bull(queueName, { redis });
|
|
20
|
-
this.nfseService = new NFSeService(options.nfseOptions ?? { mock: true });
|
|
21
|
-
this.#registerProcessor();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
#registerProcessor() {
|
|
25
|
-
this.queue.process(async (job) => {
|
|
26
|
-
const { documento } = job.data;
|
|
27
|
-
return this.nfseService.emitir(documento);
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @param {{ documento: import('../nfse/types/NFSeDocument.js').NFSeDocumento }} payload
|
|
33
|
-
*/
|
|
34
|
-
async adicionarEmissao(payload) {
|
|
35
|
-
return this.queue.add(payload, {
|
|
36
|
-
attempts: 3,
|
|
37
|
-
backoff: { type: 'exponential', delay: 5000 },
|
|
38
|
-
removeOnComplete: 100,
|
|
39
|
-
removeOnFail: 500,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** @param {(resultado: Awaited<ReturnType<NFSeService['emitir']>>, job: Bull.Job) => Promise<void>} handler */
|
|
44
|
-
onCompleted(handler) {
|
|
45
|
-
this.queue.on('completed', async (job, resultado) => {
|
|
46
|
-
await handler(resultado, job);
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
onFailed(handler) {
|
|
51
|
-
this.queue.on('failed', async (job, error) => {
|
|
52
|
-
await handler(error, job);
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async close() {
|
|
57
|
-
await this.queue.close();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
1
|
+
import Bull from 'bull';
|
|
2
|
+
import { NFSeService } from '../nfse/services/NFSeService.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fila Bull/Redis para processamento assíncrono de NFS-e.
|
|
6
|
+
*/
|
|
7
|
+
export class NFSeQueue {
|
|
8
|
+
/**
|
|
9
|
+
* @param {{
|
|
10
|
+
* redis?: { host?: string, port?: number, password?: string },
|
|
11
|
+
* queueName?: string,
|
|
12
|
+
* nfseOptions?: ConstructorParameters<typeof NFSeService>[0],
|
|
13
|
+
* }} [options]
|
|
14
|
+
*/
|
|
15
|
+
constructor(options = {}) {
|
|
16
|
+
const redis = options.redis ?? { host: '127.0.0.1', port: 6379 };
|
|
17
|
+
const queueName = options.queueName ?? 'ghinfe:nfse:emissao';
|
|
18
|
+
|
|
19
|
+
this.queue = new Bull(queueName, { redis });
|
|
20
|
+
this.nfseService = new NFSeService(options.nfseOptions ?? { mock: true });
|
|
21
|
+
this.#registerProcessor();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#registerProcessor() {
|
|
25
|
+
this.queue.process(async (job) => {
|
|
26
|
+
const { documento } = job.data;
|
|
27
|
+
return this.nfseService.emitir(documento);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {{ documento: import('../nfse/types/NFSeDocument.js').NFSeDocumento }} payload
|
|
33
|
+
*/
|
|
34
|
+
async adicionarEmissao(payload) {
|
|
35
|
+
return this.queue.add(payload, {
|
|
36
|
+
attempts: 3,
|
|
37
|
+
backoff: { type: 'exponential', delay: 5000 },
|
|
38
|
+
removeOnComplete: 100,
|
|
39
|
+
removeOnFail: 500,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** @param {(resultado: Awaited<ReturnType<NFSeService['emitir']>>, job: Bull.Job) => Promise<void>} handler */
|
|
44
|
+
onCompleted(handler) {
|
|
45
|
+
this.queue.on('completed', async (job, resultado) => {
|
|
46
|
+
await handler(resultado, job);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
onFailed(handler) {
|
|
51
|
+
this.queue.on('failed', async (job, error) => {
|
|
52
|
+
await handler(error, job);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async close() {
|
|
57
|
+
await this.queue.close();
|
|
58
|
+
}
|
|
59
|
+
}
|
package/src/queue/NFeQueue.js
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
import Bull from 'bull';
|
|
2
|
-
import { NFeService } from '../nfe/services/NFeService.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Fila Bull/Redis para processamento assíncrono de NF-e.
|
|
6
|
-
* Integra com Sequelize no worker: persista o retorno após autorização.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* const queue = new NFeQueue({ redis: { host: '127.0.0.1', port: 6379 } });
|
|
10
|
-
* await queue.adicionarEmissao({ documento, certificado });
|
|
11
|
-
* queue.processar(async (resultado) => { await NotaFiscal.create(...); });
|
|
12
|
-
*/
|
|
13
|
-
export class NFeQueue {
|
|
14
|
-
/**
|
|
15
|
-
* @param {{
|
|
16
|
-
* redis?: { host?: string, port?: number, password?: string },
|
|
17
|
-
* queueName?: string,
|
|
18
|
-
* nfeOptions?: ConstructorParameters<typeof NFeService>[0],
|
|
19
|
-
* }} [options]
|
|
20
|
-
*/
|
|
21
|
-
constructor(options = {}) {
|
|
22
|
-
const redis = options.redis ?? { host: '127.0.0.1', port: 6379 };
|
|
23
|
-
const queueName = options.queueName ?? 'ghinfe:nfe:emissao';
|
|
24
|
-
|
|
25
|
-
this.queue = new Bull(queueName, { redis });
|
|
26
|
-
this.nfeService = new NFeService(options.nfeOptions ?? { mock: true });
|
|
27
|
-
this.#registerProcessor();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
#registerProcessor() {
|
|
31
|
-
this.queue.process(async (job) => {
|
|
32
|
-
const { documento, certificado, idLote } = job.data;
|
|
33
|
-
const resultado = await this.nfeService.emitir(documento, certificado, idLote);
|
|
34
|
-
return resultado;
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @param {{
|
|
40
|
-
* documento: import('../nfe/types/NFeDocument.js').NFeDocument,
|
|
41
|
-
* certificado: { pfx: Buffer|string, senha: string },
|
|
42
|
-
* idLote?: string,
|
|
43
|
-
* }} payload
|
|
44
|
-
*/
|
|
45
|
-
async adicionarEmissao(payload) {
|
|
46
|
-
return this.queue.add(payload, {
|
|
47
|
-
attempts: 3,
|
|
48
|
-
backoff: { type: 'exponential', delay: 5000 },
|
|
49
|
-
removeOnComplete: 100,
|
|
50
|
-
removeOnFail: 500,
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Callback executado após emissão bem-sucedida (ex: salvar no Sequelize).
|
|
56
|
-
* @param {(resultado: Awaited<ReturnType<NFeService['emitir']>>, job: Bull.Job) => Promise<void>} handler
|
|
57
|
-
*/
|
|
58
|
-
onCompleted(handler) {
|
|
59
|
-
this.queue.on('completed', async (job, resultado) => {
|
|
60
|
-
await handler(resultado, job);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* @param {(error: Error, job: Bull.Job) => Promise<void>} handler
|
|
66
|
-
*/
|
|
67
|
-
onFailed(handler) {
|
|
68
|
-
this.queue.on('failed', async (job, error) => {
|
|
69
|
-
await handler(error, job);
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async close() {
|
|
74
|
-
await this.queue.close();
|
|
75
|
-
}
|
|
76
|
-
}
|
|
1
|
+
import Bull from 'bull';
|
|
2
|
+
import { NFeService } from '../nfe/services/NFeService.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fila Bull/Redis para processamento assíncrono de NF-e.
|
|
6
|
+
* Integra com Sequelize no worker: persista o retorno após autorização.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const queue = new NFeQueue({ redis: { host: '127.0.0.1', port: 6379 } });
|
|
10
|
+
* await queue.adicionarEmissao({ documento, certificado });
|
|
11
|
+
* queue.processar(async (resultado) => { await NotaFiscal.create(...); });
|
|
12
|
+
*/
|
|
13
|
+
export class NFeQueue {
|
|
14
|
+
/**
|
|
15
|
+
* @param {{
|
|
16
|
+
* redis?: { host?: string, port?: number, password?: string },
|
|
17
|
+
* queueName?: string,
|
|
18
|
+
* nfeOptions?: ConstructorParameters<typeof NFeService>[0],
|
|
19
|
+
* }} [options]
|
|
20
|
+
*/
|
|
21
|
+
constructor(options = {}) {
|
|
22
|
+
const redis = options.redis ?? { host: '127.0.0.1', port: 6379 };
|
|
23
|
+
const queueName = options.queueName ?? 'ghinfe:nfe:emissao';
|
|
24
|
+
|
|
25
|
+
this.queue = new Bull(queueName, { redis });
|
|
26
|
+
this.nfeService = new NFeService(options.nfeOptions ?? { mock: true });
|
|
27
|
+
this.#registerProcessor();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#registerProcessor() {
|
|
31
|
+
this.queue.process(async (job) => {
|
|
32
|
+
const { documento, certificado, idLote } = job.data;
|
|
33
|
+
const resultado = await this.nfeService.emitir(documento, certificado, idLote);
|
|
34
|
+
return resultado;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {{
|
|
40
|
+
* documento: import('../nfe/types/NFeDocument.js').NFeDocument,
|
|
41
|
+
* certificado: { pfx: Buffer|string, senha: string },
|
|
42
|
+
* idLote?: string,
|
|
43
|
+
* }} payload
|
|
44
|
+
*/
|
|
45
|
+
async adicionarEmissao(payload) {
|
|
46
|
+
return this.queue.add(payload, {
|
|
47
|
+
attempts: 3,
|
|
48
|
+
backoff: { type: 'exponential', delay: 5000 },
|
|
49
|
+
removeOnComplete: 100,
|
|
50
|
+
removeOnFail: 500,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Callback executado após emissão bem-sucedida (ex: salvar no Sequelize).
|
|
56
|
+
* @param {(resultado: Awaited<ReturnType<NFeService['emitir']>>, job: Bull.Job) => Promise<void>} handler
|
|
57
|
+
*/
|
|
58
|
+
onCompleted(handler) {
|
|
59
|
+
this.queue.on('completed', async (job, resultado) => {
|
|
60
|
+
await handler(resultado, job);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {(error: Error, job: Bull.Job) => Promise<void>} handler
|
|
66
|
+
*/
|
|
67
|
+
onFailed(handler) {
|
|
68
|
+
this.queue.on('failed', async (job, error) => {
|
|
69
|
+
await handler(error, job);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async close() {
|
|
74
|
+
await this.queue.close();
|
|
75
|
+
}
|
|
76
|
+
}
|