sped2sql 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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