-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
156 lines (127 loc) · 7.79 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
const { ClienteModel } = require('./models/cliente');
const { EnderecoModel } = require('./models/endereco');
const { FormaPagamentoModel } = require('./models/forma-pagamento');
const { VendaItemModel } = require('./models/venda-item');
const { VendaModel } = require('./models/venda');
const { AcrescimoDescontoModel } = require('./models/acrescimo-desconto');
const { parseFixedPoint } = require('./utils/decimal');
const PATTERN_UNICODE_NULL = /\u0000/g;
class CorruptedDataError extends Error {
/** @param { string } message */
constructor(message) {
super(message);
this.name = "CorruptedDataError";
}
}
/**
* Realiza o parsing e extrai os dados de um cupom txt de venda
* @param { string } txt conteúdo do arquivo txt do cupom de venda
* @returns { VendaModel } dados do cupom de venda
* @throws { CorruptedDataError } faz throw deste erro caso o conteúdo do cupom esteja corrompido
* @author Patrick Pissurno <contato@patrickpissurno.com.br>
*/
module.exports = function(txt){
let lines;
try {
lines = txt.split('\n');
if(lines.length < 3 || txt.replace(PATTERN_UNICODE_NULL, '').length < 1)
throw new CorruptedDataError('Arquivo corrompido.');
}
catch(ex){
throw new CorruptedDataError('Arquivo corrompido.');
}
const linha_0 = lines.find(x => x.startsWith('0'));
const linha_1 = lines.find(x => x.startsWith('1'));
const linha_2 = lines.find(x => x.startsWith('2'));
const linha_5 = lines.find(x => x.startsWith('5'));
let _tmp = linha_0.substr(40, 8);
const data = _tmp.substr(0, 4) + '-' + _tmp.substr(4, 2) + '-' + _tmp.substr(6, 2);
_tmp = linha_1.substr(1, 8);
const data_caixa = _tmp.substr(0, 4) + '-' + _tmp.substr(4, 2) + '-' + _tmp.substr(6, 2);
_tmp = linha_0.substr(48, 6);
const hora = _tmp.substr(0, 2) + ':' + _tmp.substr(2, 2) + ':' + _tmp.substr(4, 2);
const loja_cnpj = linha_0.substr(26, 14);
const tipo_venda = parseInt(linha_1.substr(20, 1));
const numero_abertura = parseInt(linha_1.substr(34, 2));
const controle_interno = parseInt(linha_1.substr(9, 10));
const controle_especifico = parseInt(linha_1.substr(21, 10));
const codigo_pdv = parseInt(linha_1.substr(31, 3));
const somatorio_valor_produtos = parseFixedPoint(linha_1.substr(197, 12), 2);
const ind_acres_desc = linha_1.substr(209, 1).trim() || null;
const valor_acres_desc = parseFixedPoint(linha_1.substr(210, 12), 2);
const acrescimo_desconto = new AcrescimoDescontoModel({ tipo: ind_acres_desc, valor: valor_acres_desc });
const venda_cancelada = linha_1.substr(19, 1) === 'S';
const quantidade_total_de_produtos = parseFixedPoint(linha_5.substr(7, 12), 2);
const somatorio_valor_unitario = parseFixedPoint(linha_5.substr(21, 14), 2);
const somatorio_valor_subtotal_item = parseFixedPoint(linha_5.substr(35, 14), 2);
const somatorio_valor_pagamento = parseFixedPoint(linha_5.substr(49, 14), 2);
const cliente_tipo = linha_1.substr(62, 1).trim() || null;
const cliente_cpf = cliente_tipo === 'J' ? null : (linha_2.substr(1, 11).trim() || linha_1.substr(66, 11).trim() || null);
const cliente_cnpj = cliente_tipo !== 'J' ? null : (linha_2.substr(1, 14).trim() || null);
const cliente_email = linha_2.substr(498, 50).trim() || null;
const cliente_nome = linha_2.substr(15, 100).trim() || linha_1.substr(77,40).trim() || null;
const cliente_telefone = linha_2.substr(548, 20).trim() || null;
const cliente_sexo = linha_2.substr(970, 1).trim() || null;
const cliente_observacao = linha_2.substr(675, 40).trim() || linha_1.substr(286, 55).trim() || null;
_tmp = linha_2.substr(659, 8).trim() || null;
const cliente_data_nascimento = !_tmp || parseInt(_tmp.substr(0, 4)) <= 1900 ? null : (_tmp.substr(0, 4) + '-' + _tmp.substr(4, 2) + '-' + _tmp.substr(6, 2));
_tmp = linha_2.substr(667, 8).trim() || null;
const cliente_data_cadastro = !_tmp || parseInt(_tmp.substr(0, 4)) <= 2000 ? null : (_tmp.substr(0, 4) + '-' + _tmp.substr(4, 2) + '-' + _tmp.substr(6, 2));
const cliente_endereco_logradouro = linha_2.substr(115, 255).trim() || null;
const cliente_endereco_bairro = linha_2.substr(420, 60).trim() || null;
const cliente_endereco_complemento = linha_2.substr(370, 50).trim() || null;
const cliente_endereco_numero = linha_2.substr(480, 9).trim() || null;
const cliente_endereco_cep = linha_2.substr(489, 8).trim() || null;
const cliente_endereco_municipio = linha_2.substr(568, 80).trim() || null;
const cliente_endereco_uf = linha_2.substr(648, 2).trim() || null;
const cliente_endereco_referencia = linha_2.substr(715, 50).trim() || null; //FIXME: confirmar comparando com o extrattor
const cliente_endereco = new EnderecoModel({ logradouro: cliente_endereco_logradouro, numero: cliente_endereco_numero, complemento: cliente_endereco_complemento, bairro: cliente_endereco_bairro, cep: cliente_endereco_cep, municipio: cliente_endereco_municipio, uf: cliente_endereco_uf, referencia: cliente_endereco_referencia });
let itens = [];
let item_found = false;
for(let i = 0; i < lines.length; i++){
if(!lines[i].startsWith('3A')){
if(!item_found)
continue;
if(lines[i].startsWith('3B') || lines[i].startsWith('5') || lines[i].startsWith('9')){
break;
}
else {
itens[itens.length - 1].observacao = [itens[itens.length - 1].observacao || '', lines[i]].join('\n').trim();
continue;
}
}
item_found = true;
const sequencia_item = parseInt(lines[i].substr(2, 3));
const codigo = parseInt(lines[i].substr(5, 10));
const nome = lines[i].substr(30, 50).trim();
const cancelado = lines[i].substr(116, 1) === 'S';
const quantidade = parseInt(lines[i].substr(86, 6));
const valor_unitario = parseFixedPoint(lines[i].substr(96, 10), 2);
const subtotal_item = parseFixedPoint(lines[i].substr(106, 10), 2);
const observacao = lines[i].substr(117).trim() || null;
itens.push(new VendaItemModel({ sequencia_item, codigo, nome, cancelado, quantidade, valor_unitario, subtotal_item, observacao }));
}
let forma_pagamento = [];
let pagamento_found = false;
for(let i = 3 + itens.length; i < lines.length; i++){
if(!lines[i].startsWith('3B')){
if(!pagamento_found)
continue;
break;
}
pagamento_found = true;
const nome = lines[i].substr(7, 20).trim() || null;
const valor = parseFixedPoint(lines[i].substr(47, 9), 2);
if(nome && valor != null)
forma_pagamento.push(new FormaPagamentoModel({ nome, valor }));
}
const cliente = new ClienteModel({ cpf: cliente_cpf, cnpj: cliente_cnpj, email: cliente_email, nome: cliente_nome, telefone: cliente_telefone, sexo: cliente_sexo, endereco: cliente_endereco.isNull() ? null : cliente_endereco, observacao: cliente_observacao, data_nascimento: cliente_data_nascimento, data_cadastro: cliente_data_cadastro });
const venda = new VendaModel({ loja_cnpj, data, data_caixa, hora, tipo_venda, numero_abertura, controle_interno, controle_especifico, codigo_pdv, cancelada: venda_cancelada, forma_pagamento, quantidade_total_de_produtos, somatorio_valor_produtos, somatorio_valor_unitario, somatorio_valor_subtotal_item, somatorio_valor_pagamento, acrescimo_desconto: acrescimo_desconto.isNull() ? null : acrescimo_desconto, cliente: cliente.isNull() ? null : cliente, itens });
return venda;
}
module.exports.ClienteModel = ClienteModel;
module.exports.EnderecoModel = EnderecoModel;
module.exports.FormaPagamentoModel = FormaPagamentoModel;
module.exports.VendaItemModel = VendaItemModel;
module.exports.VendaModel = VendaModel;
module.exports.AcrescimoDescontoModel = AcrescimoDescontoModel;