nfse-brazil-national 1.0.2 → 1.0.3
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 +24 -0
- package/package.json +6 -4
- package/src/client.js +132 -0
- package/src/templates/nfse-template.js +345 -0
package/README.md
CHANGED
|
@@ -12,6 +12,7 @@ Esta biblioteca facilita a geração, assinatura, validação e transmissão de
|
|
|
12
12
|
* **Assinatura Digital**: Assinatura XMLDSIG (padrão ICP-Brasil) utilizando certificados A1 (PFX/PKCS#12 ou PEM).
|
|
13
13
|
* **Validação XSD**: Validação local dos XMLs gerados contra os schemas oficiais antes do envio.
|
|
14
14
|
* **Comunicação API**: Métodos para emissão síncrona, consulta e cancelamento.
|
|
15
|
+
* **Geração de PDF (DANFSe)**: Geração do Documento Auxiliar da NFS-e em PDF a partir do XML.
|
|
15
16
|
* **Helpers**: Utilitários para geração de IDs (DPS/Eventos) e formatação de datas no padrão exigido.
|
|
16
17
|
|
|
17
18
|
## Instalação
|
|
@@ -20,6 +21,12 @@ Esta biblioteca facilita a geração, assinatura, validação e transmissão de
|
|
|
20
21
|
npm install nfse-brazil-national
|
|
21
22
|
```
|
|
22
23
|
|
|
24
|
+
Para melhor qualidade do QR Code na geração de PDF, recomenda-se instalar também a biblioteca `qrcode`:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install qrcode
|
|
28
|
+
```
|
|
29
|
+
|
|
23
30
|
## Uso
|
|
24
31
|
|
|
25
32
|
### Configuração
|
|
@@ -73,6 +80,22 @@ try {
|
|
|
73
80
|
}
|
|
74
81
|
```
|
|
75
82
|
|
|
83
|
+
### Geração de PDF (DANFSe)
|
|
84
|
+
|
|
85
|
+
Você pode gerar o PDF da NFS-e a partir do XML da nota.
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
// Gerar PDF (Buffer)
|
|
89
|
+
const pdfBuffer = await client.generateNfsePdf(xmlString, {
|
|
90
|
+
logo: "data:image/png;base64,..." // Opcional: Logo em Base64
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Gerar PDF comprimido (GZIP Base64)
|
|
94
|
+
const pdfGzipBase64 = await client.generateNfsePdf(xmlString, {
|
|
95
|
+
gZipB64: true
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
76
99
|
### Cancelamento de NFS-e
|
|
77
100
|
|
|
78
101
|
```javascript
|
|
@@ -103,3 +126,4 @@ const resultado = await client.cancelNfse(dadosCancelamento, chaveAcesso);
|
|
|
103
126
|
* `getDps(idDps)`: Consulta status de um DPS.
|
|
104
127
|
* `generateDpsXml(dpsData)`: Apenas gera o XML assinado (sem enviar).
|
|
105
128
|
* `validateDpsXml(xmlString)`: Valida XML contra o XSD.
|
|
129
|
+
* `generateNfsePdf(xmlString, options)`: Gera o PDF da NFS-e. Opções: `logo` (Base64), `gZipB64` (boolean).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nfse-brazil-national",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Biblioteca cliente para integração com a API Nacional da NFS-e (Nota Fiscal de Serviço Eletrônica) do Brasil.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -23,10 +23,12 @@
|
|
|
23
23
|
},
|
|
24
24
|
"public": true,
|
|
25
25
|
"dependencies": {
|
|
26
|
+
"@xmldom/xmldom": "^0.8.10",
|
|
26
27
|
"axios": "^1.13.2",
|
|
27
28
|
"handlebars": "^4.7.8",
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
29
|
+
"node-forge": "^1.3.1",
|
|
30
|
+
"pdfmake": "^0.2.10",
|
|
31
|
+
"qrcode": "^1.5.4",
|
|
32
|
+
"xml-crypto": "^6.0.0"
|
|
31
33
|
}
|
|
32
34
|
}
|
package/src/client.js
CHANGED
|
@@ -11,6 +11,9 @@ import {promisify} from "util";
|
|
|
11
11
|
import {tmpdir} from "os";
|
|
12
12
|
import forge from "node-forge";
|
|
13
13
|
import {NfseNationalError} from "./errors.js";
|
|
14
|
+
import {DOMParser} from "@xmldom/xmldom";
|
|
15
|
+
import PdfPrinter from "pdfmake";
|
|
16
|
+
import {createNfseDefinition} from "./templates/nfse-template.js";
|
|
14
17
|
|
|
15
18
|
const execAsync = promisify(exec);
|
|
16
19
|
const gzipAsync = promisify(zlib.gzip);
|
|
@@ -119,6 +122,135 @@ export class NfseNationalClient {
|
|
|
119
122
|
return this.#sendCompressedXml(url, xmlPayload, "pedidoRegistroEventoXmlGZipB64", "Failed to cancel NFS-e");
|
|
120
123
|
}
|
|
121
124
|
|
|
125
|
+
async generateNfsePdf(xmlString, options = {}) {
|
|
126
|
+
const parser = new DOMParser();
|
|
127
|
+
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
|
|
128
|
+
|
|
129
|
+
const getText = (parent, tag) => {
|
|
130
|
+
if (!parent) return "";
|
|
131
|
+
const el = parent.getElementsByTagName(tag)[0];
|
|
132
|
+
return el ? el.textContent : "";
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const infNFSe = xmlDoc.getElementsByTagName("infNFSe")[0];
|
|
136
|
+
const emit = infNFSe ? infNFSe.getElementsByTagName("emit")[0] : null;
|
|
137
|
+
const dps = xmlDoc.getElementsByTagName("DPS")[0];
|
|
138
|
+
const infDPS = dps ? dps.getElementsByTagName("infDPS")[0] : null;
|
|
139
|
+
|
|
140
|
+
const toma = infDPS ? infDPS.getElementsByTagName("toma")[0] : null;
|
|
141
|
+
const serv = infDPS ? infDPS.getElementsByTagName("serv")[0] : null;
|
|
142
|
+
const cServ = serv ? serv.getElementsByTagName("cServ")[0] : null;
|
|
143
|
+
|
|
144
|
+
const valoresDPS = infDPS ? infDPS.getElementsByTagName("valores")[0] : null;
|
|
145
|
+
const trib = valoresDPS ? valoresDPS.getElementsByTagName("trib")[0] : null;
|
|
146
|
+
const tribMun = trib ? trib.getElementsByTagName("tribMun")[0] : null;
|
|
147
|
+
const totTrib = trib ? trib.getElementsByTagName("totTrib")[0] : null;
|
|
148
|
+
const pTotTrib = totTrib ? totTrib.getElementsByTagName("pTotTrib")[0] : null;
|
|
149
|
+
|
|
150
|
+
const enderNacEmit = emit ? emit.getElementsByTagName("enderNac")[0] : null;
|
|
151
|
+
const enderNacToma = toma ? toma.getElementsByTagName("enderNac")[0] : null;
|
|
152
|
+
|
|
153
|
+
const data = {
|
|
154
|
+
logo: options.logo,
|
|
155
|
+
nNFSe: getText(infNFSe, "nNFSe"),
|
|
156
|
+
dhProc: getText(infNFSe, "dhProc"),
|
|
157
|
+
chaveAcesso: infNFSe ? infNFSe.getAttribute("Id") : "",
|
|
158
|
+
competencia: getText(infDPS, "dCompet"),
|
|
159
|
+
numDps: getText(infDPS, "nDPS"),
|
|
160
|
+
serie: getText(infDPS, "serie"),
|
|
161
|
+
dpsEmissao: getText(infDPS, "dhEmi"),
|
|
162
|
+
locPrestacao: getText(infNFSe, "xLocPrestacao"),
|
|
163
|
+
emit: {
|
|
164
|
+
xNome: getText(emit, "xNome"),
|
|
165
|
+
CNPJ: getText(emit, "CNPJ"),
|
|
166
|
+
IM: getText(emit, "IM"),
|
|
167
|
+
fone: getText(emit, "fone"),
|
|
168
|
+
enderNac: {
|
|
169
|
+
xLgr: getText(enderNacEmit, "xLgr"),
|
|
170
|
+
nro: getText(enderNacEmit, "nro"),
|
|
171
|
+
xBairro: getText(enderNacEmit, "xBairro"),
|
|
172
|
+
xMun: getText(enderNacEmit, "cMun"),
|
|
173
|
+
UF: getText(enderNacEmit, "UF"),
|
|
174
|
+
CEP: getText(enderNacEmit, "CEP")
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
toma: {
|
|
178
|
+
xNome: getText(toma, "xNome"),
|
|
179
|
+
cpfCnpj: getText(toma, "CNPJ") || getText(toma, "CPF"),
|
|
180
|
+
IM: getText(toma, "IM"),
|
|
181
|
+
fone: getText(toma, "fone"),
|
|
182
|
+
ender: enderNacToma ? `${getText(enderNacToma, "xLgr")}, ${getText(enderNacToma, "nro")} - ${getText(enderNacToma, "xBairro")}` : "",
|
|
183
|
+
municipio: enderNacToma ? `${getText(enderNacToma, "cMun")} - ${getText(enderNacToma, "UF")}` : ""
|
|
184
|
+
},
|
|
185
|
+
serv: {
|
|
186
|
+
xDescServ: getText(cServ, "xDescServ"),
|
|
187
|
+
cNBS: getText(cServ, "cNBS"),
|
|
188
|
+
xTribNac: getText(infNFSe, "xTribNac"),
|
|
189
|
+
xTribMun: getText(infNFSe, "xTribMun"),
|
|
190
|
+
cTribNac: getText(cServ, "cTribNac"),
|
|
191
|
+
cTribMun: getText(cServ, "cTribMun")
|
|
192
|
+
},
|
|
193
|
+
iss: {
|
|
194
|
+
tributacao: getText(tribMun, "tribISSQN"),
|
|
195
|
+
munIncidencia: getText(infNFSe, "xLocIncid") || getText(infNFSe, "cLocIncid"),
|
|
196
|
+
retencao: getText(tribMun, "tpRetISSQN")
|
|
197
|
+
},
|
|
198
|
+
valores: {
|
|
199
|
+
vServ: getText(valoresDPS ? valoresDPS.getElementsByTagName("vServPrest")[0] : null, "vServ"),
|
|
200
|
+
vBC: getText(tribMun, "vBC"),
|
|
201
|
+
aliq: getText(tribMun, "aliq"),
|
|
202
|
+
vISS: getText(tribMun, "vISSQN"),
|
|
203
|
+
vLiq: getText(infNFSe ? infNFSe.getElementsByTagName("valores")[0] : null, "vLiq")
|
|
204
|
+
},
|
|
205
|
+
totaisTributos: {
|
|
206
|
+
federais: getText(pTotTrib, "pTotTribFed"),
|
|
207
|
+
estaduais: getText(pTotTrib, "pTotTribEst"),
|
|
208
|
+
municipais: getText(pTotTrib, "pTotTribMun")
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// Tenta gerar QR Code como imagem se a lib 'qrcode' estiver disponível
|
|
213
|
+
try {
|
|
214
|
+
const QRCode = await import("qrcode");
|
|
215
|
+
if (data.chaveAcesso) {
|
|
216
|
+
data.qrCodeImage = await QRCode.default.toDataURL(data.chaveAcesso, {
|
|
217
|
+
errorCorrectionLevel: 'M',
|
|
218
|
+
margin: 0,
|
|
219
|
+
width: 200 // Resolução da imagem gerada
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
} catch (e) {
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const fonts = {
|
|
226
|
+
Roboto: {
|
|
227
|
+
normal: 'Helvetica',
|
|
228
|
+
bold: 'Helvetica-Bold',
|
|
229
|
+
italics: 'Helvetica-Oblique',
|
|
230
|
+
bolditalics: 'Helvetica-BoldOblique'
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const printer = new PdfPrinter(fonts);
|
|
235
|
+
const docDefinition = createNfseDefinition(data);
|
|
236
|
+
|
|
237
|
+
const pdfBuffer = await new Promise((resolve, reject) => {
|
|
238
|
+
const pdfDoc = printer.createPdfKitDocument(docDefinition);
|
|
239
|
+
const chunks = [];
|
|
240
|
+
pdfDoc.on('data', (chunk) => chunks.push(chunk));
|
|
241
|
+
pdfDoc.on('end', () => resolve(Buffer.concat(chunks)));
|
|
242
|
+
pdfDoc.on('error', (err) => reject(err));
|
|
243
|
+
pdfDoc.end();
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
if (options.gZipB64) {
|
|
247
|
+
const compressedBuffer = await gzipAsync(pdfBuffer);
|
|
248
|
+
return compressedBuffer.toString('base64');
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return pdfBuffer;
|
|
252
|
+
}
|
|
253
|
+
|
|
122
254
|
// --- Static Helper Methods ---
|
|
123
255
|
|
|
124
256
|
/**
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
export const createNfseDefinition = (data) => {
|
|
2
|
+
const v = (x, fallback = '-') => (x === undefined || x === null || x === '' ? fallback : x);
|
|
3
|
+
|
|
4
|
+
const money = (n) => {
|
|
5
|
+
if (n === undefined || n === null || n === '' || n === '-') return '-';
|
|
6
|
+
const num = typeof n === 'number' ? n : Number(String(n).replace(/[^0-9.-]/g, ''));
|
|
7
|
+
if (Number.isNaN(num)) return `R$ ${n}`;
|
|
8
|
+
return `R$ ${num.toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const formatDocument = (doc) => {
|
|
12
|
+
if (!doc) return '-';
|
|
13
|
+
const clean = String(doc).replace(/\D/g, '');
|
|
14
|
+
if (clean.length === 11) {
|
|
15
|
+
return clean.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4');
|
|
16
|
+
}
|
|
17
|
+
if (clean.length === 14) {
|
|
18
|
+
return clean.replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/, '$1.$2.$3/$4-$5');
|
|
19
|
+
}
|
|
20
|
+
return doc;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const chave = v(data.chaveAcesso);
|
|
24
|
+
|
|
25
|
+
const headerColumns = [];
|
|
26
|
+
|
|
27
|
+
headerColumns.push({
|
|
28
|
+
width: '*',
|
|
29
|
+
stack: [
|
|
30
|
+
{ text: 'Documento Auxiliar da NFS-e', style: 'title' },
|
|
31
|
+
{ text: 'NFS-e SEM VALIDADE JURÍDICA', style: 'pill' },
|
|
32
|
+
{ text: v(data.municipio, 'Município do Rio de Janeiro'), style: 'smallMuted' },
|
|
33
|
+
{ text: v(data.orgao, 'SMF / Receita Rio'), style: 'smallMuted' }
|
|
34
|
+
]
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
if (data.logo) {
|
|
38
|
+
headerColumns.push({
|
|
39
|
+
image: data.logo,
|
|
40
|
+
width: 64,
|
|
41
|
+
alignment: 'right',
|
|
42
|
+
margin: [12, 0, 0, 0]
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let qrCodeElement;
|
|
47
|
+
if (data.qrCodeImage) {
|
|
48
|
+
qrCodeElement = {
|
|
49
|
+
image: data.qrCodeImage,
|
|
50
|
+
width: 40,
|
|
51
|
+
height: 40,
|
|
52
|
+
absolutePosition: { x: 490, y: 58 }
|
|
53
|
+
};
|
|
54
|
+
} else {
|
|
55
|
+
qrCodeElement = {
|
|
56
|
+
qr: chave,
|
|
57
|
+
fit: 50,
|
|
58
|
+
absolutePosition: { x: 490, y: 65 }
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
pageMargins: [32, 20, 32, 20],
|
|
64
|
+
content: [
|
|
65
|
+
{
|
|
66
|
+
columns: headerColumns,
|
|
67
|
+
margin: [0, 0, 0, 8]
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
style: 'block',
|
|
71
|
+
stack: [
|
|
72
|
+
{ text: 'Chave de Acesso da NFS-e', style: 'label' },
|
|
73
|
+
{ text: chave, style: 'monoKey' },
|
|
74
|
+
{
|
|
75
|
+
text: 'A autenticidade desta NFS-e pode ser verificada pela leitura deste código QR ou pela consulta da chave de acesso no portal nacional da NFS-e.',
|
|
76
|
+
style: 'smallMuted',
|
|
77
|
+
margin: [0, 4, 80, 0]
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
margin: [0, 0, 0, 8]
|
|
81
|
+
},
|
|
82
|
+
qrCodeElement,
|
|
83
|
+
{
|
|
84
|
+
style: 'block',
|
|
85
|
+
table: {
|
|
86
|
+
widths: ['*', '*', '*'],
|
|
87
|
+
body: [
|
|
88
|
+
[
|
|
89
|
+
{ stack: [{ text: 'Número da NFS-e', style: 'label' }, { text: v(data.nNFSe), style: 'value' }] },
|
|
90
|
+
{ stack: [{ text: 'Competência da NFS-e', style: 'label' }, { text: v(data.competencia || data.dCompet), style: 'value' }] },
|
|
91
|
+
{ stack: [{ text: 'Data e Hora da emissão da NFS-e', style: 'label' }, { text: v(data.dhProc), style: 'value' }] }
|
|
92
|
+
],
|
|
93
|
+
[
|
|
94
|
+
{ stack: [{ text: 'Número da DPS', style: 'label' }, { text: v(data.numDps || data.dpsNumero), style: 'value' }] },
|
|
95
|
+
{ stack: [{ text: 'Série da DPS', style: 'label' }, { text: v(data.serie || data.serieDps), style: 'value' }] },
|
|
96
|
+
{ stack: [{ text: 'Data e Hora da emissão da DPS', style: 'label' }, { text: v(data.dpsEmissao || data.dhProc), style: 'value' }] }
|
|
97
|
+
]
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
layout: {
|
|
101
|
+
hLineWidth: (i) => (i === 0 || i === 1 || i === 2 ? 0.6 : 0),
|
|
102
|
+
vLineWidth: () => 0.6,
|
|
103
|
+
hLineColor: () => '#d6d6d6',
|
|
104
|
+
vLineColor: () => '#d6d6d6',
|
|
105
|
+
paddingLeft: () => 6,
|
|
106
|
+
paddingRight: () => 6,
|
|
107
|
+
paddingTop: () => 3,
|
|
108
|
+
paddingBottom: () => 3
|
|
109
|
+
},
|
|
110
|
+
margin: [0, 0, 0, 8]
|
|
111
|
+
},
|
|
112
|
+
{ text: 'EMITENTE DA NFS-e', style: 'sectionHeader' },
|
|
113
|
+
{
|
|
114
|
+
style: 'block',
|
|
115
|
+
table: {
|
|
116
|
+
widths: ['*', '*'],
|
|
117
|
+
body: [
|
|
118
|
+
[
|
|
119
|
+
{ stack: [{ text: 'Prestador do Serviço', style: 'label' }, { text: v(data.emit?.xNome), style: 'valueBold' }] },
|
|
120
|
+
{ stack: [{ text: 'CNPJ / CPF / NIF', style: 'label' }, { text: formatDocument(v(data.emit?.CNPJ || data.emit?.CPF)), style: 'value' }] }
|
|
121
|
+
],
|
|
122
|
+
[
|
|
123
|
+
{ stack: [{ text: 'Inscrição Municipal', style: 'label' }, { text: v(data.emit?.IM), style: 'value' }] },
|
|
124
|
+
{ stack: [{ text: 'Telefone', style: 'label' }, { text: v(data.emit?.fone), style: 'value' }] }
|
|
125
|
+
],
|
|
126
|
+
[
|
|
127
|
+
{ stack: [{ text: 'E-mail', style: 'label' }, { text: v(data.emit?.email), style: 'value' }] },
|
|
128
|
+
{ stack: [{ text: 'CEP', style: 'label' }, { text: v(data.emit?.enderNac?.CEP), style: 'value' }] }
|
|
129
|
+
],
|
|
130
|
+
[
|
|
131
|
+
{
|
|
132
|
+
colSpan: 2,
|
|
133
|
+
stack: [
|
|
134
|
+
{ text: 'Endereço', style: 'label' },
|
|
135
|
+
{
|
|
136
|
+
text: v(
|
|
137
|
+
data.emit?.enderNac
|
|
138
|
+
? `${v(data.emit.enderNac.xLgr)}${data.emit.enderNac.nro ? `, ${data.emit.enderNac.nro}` : ''}${data.emit.enderNac.xBairro ? `, ${data.emit.enderNac.xBairro}` : ''}`
|
|
139
|
+
: data.emit?.ender,
|
|
140
|
+
'-'
|
|
141
|
+
),
|
|
142
|
+
style: 'value',
|
|
143
|
+
margin: [0, 0, 0, 2]
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
text: v(
|
|
147
|
+
data.emit?.enderNac
|
|
148
|
+
? `${v(data.emit.enderNac.xMun)} - ${v(data.emit.enderNac.UF)}`
|
|
149
|
+
: data.emit?.municipio,
|
|
150
|
+
'-'
|
|
151
|
+
),
|
|
152
|
+
style: 'smallMuted',
|
|
153
|
+
margin: [0, 1, 0, 0]
|
|
154
|
+
}
|
|
155
|
+
]
|
|
156
|
+
},
|
|
157
|
+
{}
|
|
158
|
+
]
|
|
159
|
+
]
|
|
160
|
+
},
|
|
161
|
+
layout: 'lightHorizontalLines',
|
|
162
|
+
margin: [0, 0, 0, 8]
|
|
163
|
+
},
|
|
164
|
+
{ text: 'TOMADOR DO SERVIÇO', style: 'sectionHeader' },
|
|
165
|
+
{
|
|
166
|
+
style: 'block',
|
|
167
|
+
table: {
|
|
168
|
+
widths: ['*', '*'],
|
|
169
|
+
body: [
|
|
170
|
+
[
|
|
171
|
+
{ stack: [{ text: 'Nome / Nome Empresarial', style: 'label' }, { text: v(data.toma?.xNome), style: 'valueBold' }] },
|
|
172
|
+
{ stack: [{ text: 'CNPJ / CPF / NIF', style: 'label' }, { text: formatDocument(v(data.toma?.cpfCnpj)), style: 'value' }] }
|
|
173
|
+
],
|
|
174
|
+
[
|
|
175
|
+
{ stack: [{ text: 'Inscrição Municipal', style: 'label' }, { text: v(data.toma?.IM), style: 'value' }] },
|
|
176
|
+
{ stack: [{ text: 'Telefone', style: 'label' }, { text: v(data.toma?.fone), style: 'value' }] }
|
|
177
|
+
],
|
|
178
|
+
[
|
|
179
|
+
{
|
|
180
|
+
colSpan: 2,
|
|
181
|
+
stack: [
|
|
182
|
+
{ text: 'Endereço', style: 'label' },
|
|
183
|
+
{ text: v(data.toma?.ender), style: 'value' },
|
|
184
|
+
{ text: v(data.toma?.municipio), style: 'smallMuted', margin: [0, 1, 0, 0] }
|
|
185
|
+
]
|
|
186
|
+
},
|
|
187
|
+
{}
|
|
188
|
+
]
|
|
189
|
+
]
|
|
190
|
+
},
|
|
191
|
+
layout: 'lightHorizontalLines',
|
|
192
|
+
margin: [0, 0, 0, 8]
|
|
193
|
+
},
|
|
194
|
+
{ text: 'INTERMEDIÁRIO DO SERVIÇO', style: 'sectionHeader' },
|
|
195
|
+
{
|
|
196
|
+
text: v(data.intermediario, 'NÃO IDENTIFICADO NA NFS-e'),
|
|
197
|
+
style: 'value',
|
|
198
|
+
margin: [0, 4, 0, 8]
|
|
199
|
+
},
|
|
200
|
+
{ text: 'SERVIÇO PRESTADO', style: 'sectionHeader' },
|
|
201
|
+
{
|
|
202
|
+
style: 'block',
|
|
203
|
+
table: {
|
|
204
|
+
widths: ['*', '*'],
|
|
205
|
+
body: [
|
|
206
|
+
[
|
|
207
|
+
{ stack: [{ text: 'Código de Tributação Nacional', style: 'label' }, { text: v(data.serv?.xTribNac || data.serv?.cTribNac), style: 'value' }] },
|
|
208
|
+
{ stack: [{ text: 'Código de Tributação Municipal', style: 'label' }, { text: v(data.serv?.xTribMun || data.serv?.cTribMun), style: 'value' }] }
|
|
209
|
+
],
|
|
210
|
+
[
|
|
211
|
+
{ stack: [{ text: 'Local da Prestação', style: 'label' }, { text: v(data.locPrestacao), style: 'value' }] },
|
|
212
|
+
{ stack: [{ text: 'País da Prestação', style: 'label' }, { text: v(data.paisPrestacao), style: 'value' }] }
|
|
213
|
+
],
|
|
214
|
+
[
|
|
215
|
+
{
|
|
216
|
+
colSpan: 2,
|
|
217
|
+
stack: [
|
|
218
|
+
{ text: 'Descrição do Serviço', style: 'label' },
|
|
219
|
+
{ text: v(data.serv?.xDescServ), style: 'value' },
|
|
220
|
+
{ text: `NBS: ${v(data.serv?.cNBS)}`, style: 'smallMuted', margin: [0, 2, 0, 0] }
|
|
221
|
+
]
|
|
222
|
+
},
|
|
223
|
+
{}
|
|
224
|
+
]
|
|
225
|
+
]
|
|
226
|
+
},
|
|
227
|
+
layout: 'lightHorizontalLines',
|
|
228
|
+
margin: [0, 0, 0, 8]
|
|
229
|
+
},
|
|
230
|
+
{ text: 'TRIBUTAÇÃO MUNICIPAL', style: 'sectionHeader' },
|
|
231
|
+
{
|
|
232
|
+
style: 'block',
|
|
233
|
+
table: {
|
|
234
|
+
widths: ['*', '*', '*'],
|
|
235
|
+
body: [
|
|
236
|
+
[
|
|
237
|
+
{ stack: [{ text: 'Tributação do ISSQN', style: 'label' }, { text: v(data.iss?.tributacao), style: 'value' }] },
|
|
238
|
+
{ stack: [{ text: 'Município de Incidência do ISSQN', style: 'label' }, { text: v(data.iss?.munIncidencia), style: 'value' }] },
|
|
239
|
+
{ stack: [{ text: 'Retenção do ISSQN', style: 'label' }, { text: v(data.iss?.retencao), style: 'value' }] }
|
|
240
|
+
],
|
|
241
|
+
[
|
|
242
|
+
{ stack: [{ text: 'Valor do Serviço', style: 'label' }, { text: money(data.valores?.vServ), style: 'valueBold' }] },
|
|
243
|
+
{ stack: [{ text: 'BC ISSQN', style: 'label' }, { text: money(data.valores?.vBC), style: 'value' }] },
|
|
244
|
+
{ stack: [{ text: 'Alíquota Aplicada', style: 'label' }, { text: v(data.valores?.aliq ? `${data.valores.aliq}%` : '-'), style: 'value' }] }
|
|
245
|
+
],
|
|
246
|
+
[
|
|
247
|
+
{ stack: [{ text: 'ISSQN Apurado', style: 'label' }, { text: money(data.valores?.vISS), style: 'value' }] },
|
|
248
|
+
{ stack: [{ text: 'Desconto Incondicionado', style: 'label' }, { text: money(data.valores?.descIncond || data.valores?.vDescIncond), style: 'value' }] },
|
|
249
|
+
{ stack: [{ text: 'Total Deduções/Reduções', style: 'label' }, { text: money(data.valores?.deducoes), style: 'value' }] }
|
|
250
|
+
]
|
|
251
|
+
]
|
|
252
|
+
},
|
|
253
|
+
layout: 'lightHorizontalLines',
|
|
254
|
+
margin: [0, 0, 0, 8]
|
|
255
|
+
},
|
|
256
|
+
{ text: 'TRIBUTAÇÃO FEDERAL', style: 'sectionHeader' },
|
|
257
|
+
{
|
|
258
|
+
style: 'block',
|
|
259
|
+
table: {
|
|
260
|
+
widths: ['*', '*', '*', '*', '*'],
|
|
261
|
+
body: [
|
|
262
|
+
[
|
|
263
|
+
{ text: 'IRRF', style: 'tableHeader' },
|
|
264
|
+
{ text: 'CP', style: 'tableHeader' },
|
|
265
|
+
{ text: 'CSLL', style: 'tableHeader' },
|
|
266
|
+
{ text: 'PIS', style: 'tableHeader' },
|
|
267
|
+
{ text: 'COFINS', style: 'tableHeader' }
|
|
268
|
+
],
|
|
269
|
+
[
|
|
270
|
+
money(data.federal?.IRRF),
|
|
271
|
+
money(data.federal?.CP),
|
|
272
|
+
money(data.federal?.CSLL),
|
|
273
|
+
money(data.federal?.PIS),
|
|
274
|
+
money(data.federal?.COFINS)
|
|
275
|
+
]
|
|
276
|
+
]
|
|
277
|
+
},
|
|
278
|
+
layout: 'lightHorizontalLines',
|
|
279
|
+
margin: [0, 0, 0, 8]
|
|
280
|
+
},
|
|
281
|
+
{ text: 'VALOR TOTAL DA NFS-E', style: 'sectionHeader' },
|
|
282
|
+
{
|
|
283
|
+
style: 'block',
|
|
284
|
+
table: {
|
|
285
|
+
widths: ['*', '*', '*'],
|
|
286
|
+
body: [
|
|
287
|
+
[
|
|
288
|
+
{ stack: [{ text: 'Valor do Serviço', style: 'label' }, { text: money(data.valores?.vServ), style: 'valueBold' }] },
|
|
289
|
+
{ stack: [{ text: 'IRRF, CP, CSLL - Retidos', style: 'label' }, { text: money(data.totalFederalRetido || 0), style: 'value' }] },
|
|
290
|
+
{ stack: [{ text: 'Valor Líquido da NFS-e', style: 'label' }, { text: money(data.valores?.vLiq || data.valores?.vServ), style: 'valueBold' }] }
|
|
291
|
+
]
|
|
292
|
+
]
|
|
293
|
+
},
|
|
294
|
+
layout: 'lightHorizontalLines',
|
|
295
|
+
margin: [0, 0, 0, 8]
|
|
296
|
+
},
|
|
297
|
+
{ text: 'TOTAIS APROXIMADOS DOS TRIBUTOS', style: 'sectionHeader' },
|
|
298
|
+
{
|
|
299
|
+
style: 'block',
|
|
300
|
+
table: {
|
|
301
|
+
widths: ['*', '*', '*'],
|
|
302
|
+
body: [
|
|
303
|
+
[
|
|
304
|
+
{ stack: [{ text: 'Federais', style: 'label' }, { text: money(data.totaisTributos?.federais), style: 'value' }] },
|
|
305
|
+
{ stack: [{ text: 'Estaduais', style: 'label' }, { text: money(data.totaisTributos?.estaduais), style: 'value' }] },
|
|
306
|
+
{ stack: [{ text: 'Municipais', style: 'label' }, { text: money(data.totaisTributos?.municipais), style: 'value' }] }
|
|
307
|
+
]
|
|
308
|
+
]
|
|
309
|
+
},
|
|
310
|
+
layout: 'lightHorizontalLines',
|
|
311
|
+
margin: [0, 0, 0, 8]
|
|
312
|
+
},
|
|
313
|
+
{ text: 'INFORMAÇÕES COMPLEMENTARES', style: 'sectionHeader' },
|
|
314
|
+
{ text: `NBS: ${v(data.serv?.cNBS)}`, style: 'value', margin: [0, 4, 0, 0] }
|
|
315
|
+
],
|
|
316
|
+
|
|
317
|
+
styles: {
|
|
318
|
+
title: { fontSize: 12, bold: true },
|
|
319
|
+
pill: {
|
|
320
|
+
fontSize: 8,
|
|
321
|
+
bold: true,
|
|
322
|
+
color: '#FF0000',
|
|
323
|
+
margin: [0, 4, 0, 4]
|
|
324
|
+
},
|
|
325
|
+
sectionHeader: {
|
|
326
|
+
fontSize: 9,
|
|
327
|
+
bold: true,
|
|
328
|
+
fillColor: '#eeeeee',
|
|
329
|
+
margin: [0, 4, 0, 2],
|
|
330
|
+
color: '#000000'
|
|
331
|
+
},
|
|
332
|
+
label: { fontSize: 7, color: '#555555', margin: [0, 0, 0, 3] },
|
|
333
|
+
value: { fontSize: 8, color: '#000000' },
|
|
334
|
+
valueBold: { fontSize: 8, bold: true, color: '#000000' },
|
|
335
|
+
smallMuted: { fontSize: 7, color: '#666666', margin: [0, 0, 0, 3] },
|
|
336
|
+
monoKey: { fontSize: 8, bold: true, characterSpacing: 0.2 },
|
|
337
|
+
tableHeader: { bold: true, fontSize: 8, color: '#000000' },
|
|
338
|
+
block: { margin: [0, 0, 0, 0] }
|
|
339
|
+
},
|
|
340
|
+
|
|
341
|
+
defaultStyle: {
|
|
342
|
+
fontSize: 8
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
};
|