UNPKG

degust-cupom-txt

Version:

Module capaz de extrair os dados dos cupons .txt que o PDV Linx Degust gera

157 lines (127 loc) 7.97 kB
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;