sped2sql 1.0.4

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.
@@ -0,0 +1,68 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module SPED2SQL
3
+ module SQL
4
+ class Parser
5
+ attr_reader :dados, :tbl_prefix, :tbl_sufix
6
+
7
+ HEADER = "/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\r\n" \
8
+ "/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\r\n" \
9
+ "/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\r\n" \
10
+ "/*!40101 SET NAMES utf8 */;\r\n" \
11
+ "/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\r\n" \
12
+ "/*!40103 SET TIME_ZONE='+00:00' */;\r\n" \
13
+ "/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\r\n" \
14
+ "/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\r\n" \
15
+ "/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\r\n"
16
+
17
+ FOOTER = "/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\r\n" \
18
+ "/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\r\n" \
19
+ "/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\r\n" \
20
+ "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\r\n" \
21
+ "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\r\n" \
22
+ "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\r\n" \
23
+ "/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\r\n"
24
+
25
+ def initialize(dados, options = {})
26
+ @tbl_prefix = options[:tbl_prefix] || ''
27
+ @tbl_sufix = options[:tbl_sufix] || ''
28
+ @dados = dados
29
+ self
30
+ end
31
+
32
+ def parse!
33
+ output = []
34
+ inserts_agrupados.each do |registro, inserts|
35
+ tabela = nome_tabela(registro)
36
+
37
+ output << "LOCK TABLES `#{ tabela }` WRITE;"
38
+ output << "/*!40000 ALTER TABLE `#{ tabela }` DISABLE KEYS */;"
39
+ output << "INSERT INTO #{ tabela } VALUES ('',#{ inserts.join("),('',") });"
40
+ output << "/*!40000 ALTER TABLE `#{ tabela }` ENABLE KEYS */;"
41
+ output << "UNLOCK TABLES;"
42
+ end
43
+
44
+ "#{ HEADER }#{ output.join("\r\n") }\r\n#{ FOOTER }"
45
+ end
46
+
47
+ class << self
48
+ def to_sql(dados, options = {})
49
+ new(dados, options).parse!
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def inserts_agrupados
56
+ inserts = Hash.new { |k, v| k[v] = [] }
57
+ dados.each do |linha|
58
+ inserts[linha[0]] << linha[0..-1].map { |r| "'#{r}'" }.join(',')
59
+ end
60
+ inserts
61
+ end
62
+
63
+ def nome_tabela(tabela)
64
+ "#{ @tbl_prefix }#{ tabela }#{ @tbl_sufix }"
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ module SPED2SQL
4
+ VERSION = '1.0.4'
5
+ end
@@ -0,0 +1 @@
1
+ |0000|0000|0000|
@@ -0,0 +1,3 @@
1
+ |0000|string|string|date|decimal|string|
2
+ |0001|string|string|decimal|
3
+ |0002|string|string|decimal|string|
@@ -0,0 +1,3 @@
1
+ |0000|Teste|31122014|1000,50|Teste Fim|
2
+ |0001|Empresa X|1520,37|
3
+ |0002|Fornecedor|5200537,21|Dados|
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require "codeclimate-test-reporter"
3
+ CodeClimate::TestReporter.start
4
+
5
+ require 'sped2sql'
6
+
7
+ RSpec.configure do |config|
8
+ config.order = :random
9
+ end
10
+
11
+ module FiltroVazio
12
+ def self.call(env)
13
+ env
14
+ end
15
+ end
16
+
17
+ module FiltroAdd
18
+ def self.call(env)
19
+ env[:total] = env[:total] + 100
20
+ env
21
+ end
22
+ end
@@ -0,0 +1,106 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module SPED2SQL
5
+ describe Conversor do
6
+
7
+ let(:arquivo_sped) { File.expand_path(File.join('spec','resources', 'sped.txt')) }
8
+ let(:arquivo_mapa) { File.expand_path(File.join('spec','resources', 'mapa.txt')) }
9
+
10
+ it "deveria validar se o arquivo sped existe ou nao" do
11
+ expect { Conversor.new('???', arquivo_mapa) }.
12
+ to raise_error(ArgumentError, "Arquivo inexistente: ???")
13
+
14
+ expect { Conversor.new(arquivo_sped, arquivo_mapa) }.
15
+ not_to raise_error
16
+ end
17
+
18
+ it "deveria validar se o arquivo de layout existe ou nao" do
19
+ expect { Conversor.new(arquivo_sped, '???') }.
20
+ to raise_error(ArgumentError, "Arquivo inexistente: ???")
21
+ end
22
+
23
+ it "deveria instanciar com as tasks default" do
24
+ conversor = Conversor.new(arquivo_sped, arquivo_mapa)
25
+ expect( conversor.tasks ).to eq([Pipeline::NormalizaSQL, Pipeline::AddHash])
26
+ end
27
+
28
+ it "deveria instaciar com o template informado" do
29
+ conversor = Conversor.new(arquivo_sped, :efd_icms_ipi)
30
+ expect( conversor.template ).to eq( File.expand_path("templates/efd_icms_ipi.txt") )
31
+ end
32
+
33
+ it "deveriar validar se o template informado é valido" do
34
+ expect { Conversor.new(arquivo_sped, :fake_template) }.
35
+ to raise_error(ArgumentError, "Template inexistente: #{:fake_template.to_s}")
36
+ end
37
+
38
+ it "deveria instanciar sem tasks quando informado" do
39
+ conversor = Conversor.new(arquivo_sped, arquivo_mapa, {tasks: :vazio})
40
+ expect( conversor.tasks ).to eq([])
41
+ end
42
+
43
+ it "deveria instanciar apenas com as tasks informadas" do
44
+ conversor = Conversor.new(arquivo_sped, arquivo_mapa, {tasks: [::FiltroVazio, ::FiltroAdd]})
45
+ expect( conversor.tasks ).to eq([::FiltroVazio, ::FiltroAdd])
46
+ end
47
+
48
+ describe 'Conversão' do
49
+
50
+ it "deveria agrupar a memoria por registro" do
51
+ conversor = Conversor.new(arquivo_sped, arquivo_mapa, {tasks: :vazio})
52
+ conversor.converter!
53
+ expect( conversor.memoria ).to eq({'0000' => [['0000','Teste','31122014','1000,50','Teste Fim']],
54
+ '0001' => [['0001','Empresa X','1520,37']],
55
+ '0002' => [['0002','Fornecedor','5200537,21','Dados']]})
56
+ end
57
+
58
+ it "deveria modificar apenas com o pipe informado" do
59
+ conversor = Conversor.new(arquivo_sped, arquivo_mapa, {tasks: [Pipeline::NormalizaSQL]})
60
+ conversor.converter!
61
+ expect( conversor.saida ).to eq([['0000','Teste','2014-12-31','1000.50','Teste Fim'],
62
+ ['0001','Empresa X','1520.37'],
63
+ ['0002','Fornecedor','5200537.21','Dados']])
64
+ end
65
+
66
+ it "deveria converter utilizando os pipes default" do
67
+ hash = Formatters::GeraHash.get_hash
68
+ allow(Formatters::GeraHash).to receive(:get_hash).and_return(hash)
69
+
70
+ conversor = Conversor.new(arquivo_sped, arquivo_mapa)
71
+ conversor.converter!
72
+ expect( conversor.saida ).to eq([['0000','Teste','2014-12-31','1000.50','Teste Fim', hash],
73
+ ['0001','Empresa X','1520.37', hash],
74
+ ['0002','Fornecedor','5200537.21','Dados', hash]])
75
+ end
76
+
77
+ it "deveria converter para sql" do
78
+ hash = Formatters::GeraHash.get_hash
79
+ allow(Formatters::GeraHash).to receive(:get_hash).and_return(hash)
80
+
81
+ conversor = Conversor.new(arquivo_sped, arquivo_mapa)
82
+ conversor.converter!
83
+
84
+ sql = "LOCK TABLES `0000` WRITE;\r\n" \
85
+ "/*!40000 ALTER TABLE `0000` DISABLE KEYS */;\r\n" \
86
+ "INSERT INTO 0000 VALUES ('','0000','Teste','2014-12-31','1000.50','Teste Fim','#{hash}');\r\n" \
87
+ "/*!40000 ALTER TABLE `0000` ENABLE KEYS */;\r\n" \
88
+ "UNLOCK TABLES;\r\n" \
89
+ "LOCK TABLES `0001` WRITE;\r\n" \
90
+ "/*!40000 ALTER TABLE `0001` DISABLE KEYS */;\r\n" \
91
+ "INSERT INTO 0001 VALUES ('','0001','Empresa X','1520.37','#{hash}');\r\n" \
92
+ "/*!40000 ALTER TABLE `0001` ENABLE KEYS */;\r\n" \
93
+ "UNLOCK TABLES;\r\n" \
94
+ "LOCK TABLES `0002` WRITE;\r\n" \
95
+ "/*!40000 ALTER TABLE `0002` DISABLE KEYS */;\r\n" \
96
+ "INSERT INTO 0002 VALUES ('','0002','Fornecedor','5200537.21','Dados','#{hash}');\r\n" \
97
+ "/*!40000 ALTER TABLE `0002` ENABLE KEYS */;\r\n" \
98
+ "UNLOCK TABLES;\r\n" \
99
+
100
+ expect( conversor.to_sql ).to include(sql)
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module SPED2SQL
5
+ module Formatters
6
+ describe GeraHash do
7
+
8
+ it "deveria responder a get_hash" do
9
+ expect( GeraHash ).to respond_to :get_hash
10
+ end
11
+
12
+ # (sem utilidade) melhorar ou remover
13
+ it "deveria criar hashs distintos" do
14
+ ids = []
15
+ 1.upto(100) { ids << GeraHash.get_hash }
16
+ expect( ids.uniq.size ).to eq 100
17
+ end
18
+
19
+ it "deveria gerar hashs com 36 caracts de tamanho" do
20
+ expect( GeraHash.get_hash.length ).to eq 36
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,47 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module SPED2SQL
5
+ module Formatters
6
+ describe StringConverter do
7
+
8
+ let(:conversores) { [:string, :date, :decimal] }
9
+
10
+ it "deveria responder aos conversores" do
11
+ conversores.each do |conversor|
12
+ expect( StringConverter ).to respond_to(conversor)
13
+ end
14
+ end
15
+
16
+ it "deveria retornar uma string vazia para dados nulos ou vazios" do
17
+ conversores.each do |conversor|
18
+ expect( StringConverter.converter("", conversor) ).to eq ""
19
+ expect( StringConverter.converter(nil, conversor) ).to eq ""
20
+ end
21
+ end
22
+
23
+ it "deveria retornar a string" do
24
+ expect( StringConverter.converter("123", :string) ).to eq "123"
25
+ end
26
+
27
+ it "deveria 'escapar' strings quem contem apostrofos" do
28
+ expect( StringConverter.converter("test'e'a", :string) ).to eq "test\\'e\\'a"
29
+ end
30
+
31
+ it "deveria retornar o mesmo dado se o conversor nao existir" do
32
+ expect( StringConverter.conveter("010101", :no_converter) ).to eq "010101"
33
+ end
34
+
35
+ it "deveria formatar a string para data" do
36
+ expect( StringConverter.converter("01102014", :date) ).to eq "2014-10-01"
37
+ end
38
+
39
+ it "deveria formatar a string para decimal" do
40
+ expect( StringConverter.converter("100,25", :decimal) ).to eq "100.25"
41
+ expect( StringConverter.converter("1.100,25", :decimal) ).to eq "1100.25"
42
+ expect( StringConverter.converter("1.000.000,25", :decimal) ).to eq "1000000.25"
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,40 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module SPED2SQL
5
+ module Layout
6
+ describe Mapa do
7
+
8
+ let(:mapa) { File.expand_path(File.join('spec','resources', 'mapa.txt')) }
9
+
10
+ it "deveria carregar o layout para um hash" do
11
+ expect( Mapa.carrega!(mapa) ).
12
+ to eq({
13
+ "0000" => [:string, :string, :date, :decimal, :string],
14
+ "0001" => [:string, :string, :decimal],
15
+ "0002" => [:string, :string, :decimal, :string]
16
+ })
17
+ end
18
+
19
+ it "deveria ter uma pasta valida para os tempaltes" do
20
+ expect( File.exists?(Layout::TEMPLATE_PATH) ).to be true
21
+ end
22
+
23
+ it "deveria responder a arquivo_template" do
24
+ expect( Mapa ).to respond_to :arquivo_template
25
+ end
26
+
27
+ it "deveria retornar arquivos validos para os templates default" do
28
+ [:efd_icms_ipi].each do |tipo|
29
+ expect( File.exists?(Mapa.arquivo_template(tipo)) ).to be true
30
+ end
31
+ end
32
+
33
+ it "deveria lançar excessao quando template default nao existe" do
34
+ expect { Mapa.arquivo_template(:fake_template) }.
35
+ to raise_error(ArgumentError, "Template inexistente: #{:fake_template.to_s}")
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module SPED2SQL
5
+ module Pipeline
6
+ describe AddHash do
7
+
8
+ before do
9
+ @hash = Formatters::GeraHash.get_hash
10
+ allow(Formatters::GeraHash).to receive(:get_hash).and_return(@hash)
11
+ end
12
+
13
+ let(:env) { { original: ['0000','Teste','31122014','1000,50','Teste Fim'],
14
+ final: ['0000','Teste','31122014','1000,50','Teste Fim'],
15
+ mapa: ['0000','string','date','decimal','string'],
16
+ memoria: {},
17
+ saida: [] } }
18
+
19
+ let(:saida) { { original: ['0000','Teste','31122014','1000,50','Teste Fim'],
20
+ final: ['0000','Teste','31122014','1000,50','Teste Fim', @hash],
21
+ mapa: ['0000','string','date','decimal','string'],
22
+ memoria: {},
23
+ saida: [] } }
24
+
25
+ it { should respond_to :call }
26
+
27
+ it "deveria converter os dados da linha de acordo com o tipo da coluna no mapa" do
28
+ expect( AddHash.call(env) ).to eq(saida)
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,54 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module SPED2SQL
5
+ module Pipeline
6
+ describe Base do
7
+
8
+ let(:base_obj) { Base.new }
9
+
10
+ it { should respond_to :execute }
11
+ it { should respond_to :<< }
12
+
13
+ it "deveria instanciar sem tasks quando vazio" do
14
+ expect( Base.new.tasks ).to eq([])
15
+ end
16
+
17
+ it "deveria instanciar com as tasks informadas" do
18
+ expect( Base.new([::FiltroVazio, ::FiltroAdd]).tasks ).
19
+ to eq([::FiltroVazio, ::FiltroAdd])
20
+ end
21
+
22
+ it "deveria adicionar novas tarefas" do
23
+ base_obj << ::FiltroVazio
24
+ expect( base_obj.tasks ).to eq([::FiltroVazio])
25
+
26
+ base_obj << ::FiltroAdd
27
+ expect( base_obj.tasks ).to eq([::FiltroVazio, ::FiltroAdd])
28
+ end
29
+
30
+ it "deveria retornar um objeto Base apos adicionar tarefa" do
31
+ expect( base_obj << ::FiltroAdd ).to be_a(Base)
32
+ expect( (base_obj << ::FiltroVazio).tasks ).to eq([::FiltroAdd, ::FiltroVazio])
33
+ end
34
+
35
+ it "deveria adicionar novas tarefas em linha" do
36
+ expect( base_obj.tasks ).to eq([])
37
+ base_obj << ::FiltroVazio << ::FiltroAdd
38
+ expect( base_obj.tasks ).to eq([::FiltroVazio, ::FiltroAdd])
39
+ end
40
+
41
+ it "deveria executar os filtros adicionados" do
42
+ base_obj << FiltroVazio
43
+ expect( base_obj.execute({total: 1}) ).to eq({total: 1})
44
+
45
+ base_obj << FiltroAdd
46
+ expect( base_obj.execute({total: 1}) ).to eq({total: 101})
47
+
48
+ base_obj << FiltroAdd
49
+ expect( base_obj.execute({total: 1}) ).to eq({total: 201})
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module SPED2SQL
5
+ module Pipeline
6
+ describe NormalizaSQL do
7
+
8
+ it { should respond_to :call }
9
+
10
+ let(:env) { { original: ['0000','Teste','31122014','1000,50','Teste Fim'],
11
+ final: ['0000','Teste','31122014','1000,50','Teste Fim'],
12
+ mapa: {"0000" => ['0000','string','date','decimal','string']},
13
+ memoria: {},
14
+ saida: [] } }
15
+
16
+ let(:saida) { { original: ['0000','Teste','31122014','1000,50','Teste Fim'],
17
+ final: ['0000','Teste','2014-12-31','1000.50','Teste Fim'],
18
+ mapa: {"0000" => ['0000','string','date','decimal','string']},
19
+ memoria: {},
20
+ saida: [] } }
21
+
22
+ it "deveria converter os dados da linha de acordo com o tipo da coluna no mapa" do
23
+ expect( NormalizaSQL.call(env) ).to eq(saida)
24
+ end
25
+
26
+ end
27
+ end
28
+ end