teodoro 0.0.6 → 0.0.11

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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/bin/teodoro +1 -1
  3. data/lib/teodoro.rb +71 -3
  4. data/lib/teodoro/arquivo_de_evento.rb +16 -15
  5. data/lib/teodoro/arquivo_de_evento_de_tabela.rb +2 -15
  6. data/lib/teodoro/arquivo_de_evento_exceto_de_exclusao.rb +25 -0
  7. data/lib/teodoro/arquivo_de_evento_nao_periodico.rb +8 -17
  8. data/lib/teodoro/arquivo_de_origem.rb +1 -1
  9. data/lib/teodoro/arquivo_xml.rb +57 -48
  10. data/lib/teodoro/console.rb +2 -6
  11. data/lib/teodoro/empresa.rb +48 -15
  12. data/lib/teodoro/leiaute_2.rb +24 -0
  13. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s1000.rb +1 -1
  14. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s1005.rb +1 -1
  15. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s1010.rb +7 -3
  16. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s1020.rb +1 -1
  17. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s1030.rb +1 -1
  18. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s1040.rb +1 -1
  19. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s1050.rb +1 -1
  20. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s1070.rb +1 -1
  21. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s2190.rb +1 -1
  22. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s2200.rb +27 -10
  23. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s2205.rb +2 -2
  24. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s2206.rb +1 -1
  25. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s2230.rb +1 -1
  26. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s2250.rb +2 -2
  27. data/lib/teodoro/leiaute_2/arquivo_s2299.rb +310 -0
  28. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s2300.rb +20 -2
  29. data/lib/teodoro/{leiaute_2_4_1 → leiaute_2}/arquivo_s2306.rb +1 -1
  30. data/lib/teodoro/leiaute_2/arquivo_s2399.rb +303 -0
  31. data/lib/teodoro/leiaute_2/arquivo_s3000.rb +41 -0
  32. data/lib/teodoro/obj.rb +5 -0
  33. metadata +38 -20
  34. data/lib/teodoro/execucao.rb +0 -76
  35. data/lib/teodoro/leiaute_2_4_1.rb +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0420ba2d797c7218d8a11c5c6457bd8501e98d4b0173c837577208729b14331e
4
- data.tar.gz: 77bebe3f5a7a56a3f64951013edde6312d94515438fc4c7038bc30b8f2a5b724
3
+ metadata.gz: 1c9deae607c9ff37a06e53ec8cb179d250a85ed8fda4e2480892cc4169453e43
4
+ data.tar.gz: d9f73ef82b8803e52fb33b57e4b25549d84c004e2cae59c4261e6f9694f5de6c
5
5
  SHA512:
6
- metadata.gz: e8c054279ffb44d97a167853f65282dffe44816d16d8d50452309b0924f473babe74f89e7d777d65c31c83acf21e653d2ce1891a33ca4d6f54d282b1b471a802
7
- data.tar.gz: a858db4b007cce3931a23078f3930572429b410c3d821433ecd5cdefce5f7e21b9c302cc7cb3911e72750b36226879d9e9aac14859c859291b508f8bfeb52582
6
+ metadata.gz: 11b1fac346b51fae9b6cc45f11881acb1e2c9c594afdabd6a943de5fe201f76f464c20bf084fb910e164d3886d2a22a02b1b0a34f28f43c98b0edab5f8591521
7
+ data.tar.gz: 17b9915e3a32d1a8dda9de0626881eb817f8476048cbe7519ebf74fab442ff43e28887edf8c3775931d060e1857d66e97f0284c79b7b7d22b13966287177566e
data/bin/teodoro CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'teodoro'
3
- Teodoro.call
3
+ Teodoro.call(ARGV)
data/lib/teodoro.rb CHANGED
@@ -1,7 +1,75 @@
1
- require_relative 'teodoro/execucao'
1
+ require 'nokogiri'
2
+ require 'os'
3
+ require 'zip'
4
+
5
+ require_relative 'teodoro/console'
6
+ require_relative 'teodoro/empresa'
7
+ require_relative 'teodoro/obj'
2
8
 
3
9
  module Teodoro
4
- def self.call
5
- Execucao.new(ARGV).call
10
+ def self.call(args)
11
+ Execution.new(args).call
12
+ end
13
+
14
+ class Execution
15
+ NOME_DO_PROGRAMA = 'teodoro'.freeze
16
+
17
+ private
18
+
19
+ def initialize(args)
20
+ @args = args
21
+ end
22
+
23
+ attr_reader :args
24
+
25
+ public
26
+
27
+ def call
28
+ validar_argumentos
29
+ validar_existencia_do_diretorio_de_origem
30
+ validar_que_diretorio_de_origem_nao_esta_vazio
31
+ validar_que_diretorio_de_destino_esta_vazio
32
+
33
+ processar_empresas
34
+ end
35
+
36
+ private
37
+
38
+ def validar_argumentos
39
+ erro "#{NOME_DO_PROGRAMA} [diretório de origem] [diretório de destino]" unless args.size == 2
40
+ end
41
+
42
+ def validar_existencia_do_diretorio_de_origem
43
+ erro 'Diretório de origem não existe.' unless File.directory?(origem)
44
+ end
45
+
46
+ def origem
47
+ @origem ||= args[0]
48
+ end
49
+
50
+ def validar_que_diretorio_de_origem_nao_esta_vazio
51
+ erro 'Diretório de origem vazio.' if Dir.empty?(origem)
52
+ end
53
+
54
+ def validar_que_diretorio_de_destino_esta_vazio
55
+ erro 'Diretório de destino deve estar vazio.' unless Dir.empty?(destino)
56
+ end
57
+
58
+ def destino
59
+ @destino ||= args[1]
60
+ end
61
+
62
+ def erro(erro)
63
+ puts erro
64
+ exit
65
+ end
66
+
67
+ def processar_empresas
68
+ empresas.each(&:processar)
69
+ end
70
+
71
+ def empresas
72
+ Dir[File.join(origem, '*')].map { |caminho| Empresa.new(caminho: caminho, destino: destino) }
73
+ end
6
74
  end
7
75
  end
@@ -2,30 +2,31 @@ module Teodoro
2
2
  module ArquivoDeEvento
3
3
  private
4
4
 
5
- attr_reader :xml_do_evento, :xml_do_recibo, :destino_dos_arquivos_data
6
-
7
- def criar_arquivo_data
8
- File.write(caminho_do_arquivo_data, conteudo_do_arquivo_data)
5
+ def initialize(empresa:, evento:, recibo:)
6
+ @empresa = empresa
7
+ @evento = evento
8
+ @recibo = recibo
9
9
  end
10
10
 
11
- def evento
12
- @evento ||= XML.new(xml_do_evento)
13
- end
11
+ attr_reader :empresa, :evento, :recibo
14
12
 
15
- def conteudo_do_arquivo_data
16
- (itens_do_conteudo_do_arquivo_data.map { "#{_1}=#{_2}" } + ['']).join("\n")
13
+ def processo_de_emissao_do_evento
14
+ evento["#{noh_principal_do_evento}/ideEvento/procEmi"]
17
15
  end
18
16
 
19
- def versao_do_aplicativo_de_processamento_do_evento
20
- recibo['retornoEvento/processamento/versaoAppProcessamento']
17
+ def criar_caminho_do_arquivo_data(nome_do_arquivo)
18
+ File.join(
19
+ destino_dos_arquivos_data,
20
+ "#{windows? ? nome_do_arquivo.gsub(%r{[<|>:"/\\?*]}, '_') : nome_do_arquivo}.data"
21
+ )
21
22
  end
22
23
 
23
- def tipo_de_inscricao_do_empregador
24
- @tipo_de_inscricao_do_empregador ||= evento["#{noh_principal_do_evento}/ideEmpregador/tpInsc"]
24
+ def destino_dos_arquivos_data
25
+ empresa.destino_dos_arquivos_data
25
26
  end
26
27
 
27
- def recibo
28
- @recibo ||= XML.new(xml_do_recibo)
28
+ def windows?
29
+ OS.windows?
29
30
  end
30
31
  end
31
32
  end
@@ -1,16 +1,6 @@
1
1
  module Teodoro
2
2
  module ArquivoDeEventoDeTabela
3
- include ArquivoDeEvento
4
-
5
- private
6
-
7
- def initialize(xml_do_evento:, xml_do_recibo:, destino_dos_arquivos_data:)
8
- @xml_do_evento = xml_do_evento
9
- @xml_do_recibo = xml_do_recibo
10
- @destino_dos_arquivos_data = destino_dos_arquivos_data
11
- end
12
-
13
- public
3
+ include ArquivoDeEventoExcetoDeExclusao
14
4
 
15
5
  def processar
16
6
  deletar_arquivo_data_original if alteracao? || exclusao?
@@ -38,10 +28,7 @@ module Teodoro
38
28
  end
39
29
 
40
30
  def obter_caminho_do_arquivo_data(inicio_da_validade)
41
- File.join(
42
- destino_dos_arquivos_data,
43
- "#{nome_base_do_arquivo_data}[#{inicio_da_validade.delete('-')}].data"
44
- )
31
+ criar_caminho_do_arquivo_data("#{nome_base_do_arquivo_data}[#{inicio_da_validade.delete('-')}]")
45
32
  end
46
33
 
47
34
  def nome_base_do_arquivo_data
@@ -0,0 +1,25 @@
1
+ module Teodoro
2
+ module ArquivoDeEventoExcetoDeExclusao
3
+ include ArquivoDeEvento
4
+
5
+ private
6
+
7
+ def criar_arquivo_data
8
+ raise caminho_do_arquivo_data if File.exist?(caminho_do_arquivo_data)
9
+
10
+ File.write(caminho_do_arquivo_data, conteudo_do_arquivo_data)
11
+ end
12
+
13
+ def conteudo_do_arquivo_data
14
+ (itens_do_conteudo_do_arquivo_data.map { "#{_1}=#{_2}" } + ['']).join("\n")
15
+ end
16
+
17
+ def versao_do_aplicativo_de_processamento_do_evento
18
+ recibo['retornoEvento/processamento/versaoAppProcessamento']
19
+ end
20
+
21
+ def tipo_de_inscricao_do_empregador
22
+ @tipo_de_inscricao_do_empregador ||= evento["#{noh_principal_do_evento}/ideEmpregador/tpInsc"]
23
+ end
24
+ end
25
+ end
@@ -1,19 +1,6 @@
1
1
  module Teodoro
2
2
  module ArquivoDeEventoNaoPeriodico
3
- include ArquivoDeEvento
4
-
5
- private
6
-
7
- def initialize(xml_do_evento:, xml_do_recibo:, destino_dos_arquivos_data:, de_recibo_para_nome_do_arquivo_data:)
8
- @xml_do_evento = xml_do_evento
9
- @xml_do_recibo = xml_do_recibo
10
- @destino_dos_arquivos_data = destino_dos_arquivos_data
11
- @de_recibo_para_nome_do_arquivo_data = de_recibo_para_nome_do_arquivo_data
12
- end
13
-
14
- attr_reader :de_recibo_para_nome_do_arquivo_data
15
-
16
- public
3
+ include ArquivoDeEventoExcetoDeExclusao
17
4
 
18
5
  def processar
19
6
  deletar_arquivo_data_original if retificacao?
@@ -32,15 +19,19 @@ module Teodoro
32
19
  end
33
20
 
34
21
  def caminho_do_arquivo_data_original
35
- File.join(destino_dos_arquivos_data, "#{nome_do_arquivo_original}.data")
22
+ criar_caminho_do_arquivo_data(nome_do_arquivo_original)
36
23
  end
37
24
 
38
25
  def nome_do_arquivo_original
39
26
  de_recibo_para_nome_do_arquivo_data[numero_do_recibo_a_retificar]
40
27
  end
41
28
 
29
+ def de_recibo_para_nome_do_arquivo_data
30
+ empresa.de_recibo_para_nome_do_arquivo_data
31
+ end
32
+
42
33
  def numero_do_recibo_a_retificar
43
- @numero_do_recibo_a_retificar ||= evento["#{noh_principal_do_evento}/ideEvento/nrRecibo"]
34
+ evento["#{noh_principal_do_evento}/ideEvento/nrRecibo"]
44
35
  end
45
36
 
46
37
  def registrar_recibo
@@ -52,7 +43,7 @@ module Teodoro
52
43
  end
53
44
 
54
45
  def caminho_do_arquivo_data
55
- File.join(destino_dos_arquivos_data, "#{nome_do_arquivo_data}.data")
46
+ criar_caminho_do_arquivo_data(nome_do_arquivo_data)
56
47
  end
57
48
  end
58
49
  end
@@ -14,7 +14,7 @@ module Teodoro
14
14
  public
15
15
 
16
16
  def descompactar
17
- puts File.basename(caminho)
17
+ Console.print "descompactando #{File.basename(caminho)}..."
18
18
 
19
19
  Zip::File.open(caminho) do |zip|
20
20
  zip
@@ -1,72 +1,80 @@
1
1
  require_relative 'arquivo_de_evento'
2
+ require_relative 'arquivo_de_evento_exceto_de_exclusao'
2
3
  require_relative 'arquivo_de_evento_de_tabela'
3
4
  require_relative 'arquivo_de_evento_nao_periodico'
4
5
  require_relative 'cnpj'
5
- require_relative 'leiaute_2_4_1'
6
+ require_relative 'leiaute_2'
6
7
  require_relative 'xml'
7
8
 
8
9
  module Teodoro
9
10
  class ArquivoXML
11
+ TIPOS_DE_EVENTO_PROCESSAVEIS = %w[
12
+ S1000
13
+ S1005
14
+ S1010
15
+ S1020
16
+ S1030
17
+ S1040
18
+ S1050
19
+ S1070
20
+ S2190
21
+ S2200
22
+ S2205
23
+ S2206
24
+ S2230
25
+ S2250
26
+ S2299
27
+ S2300
28
+ S2306
29
+ S2399
30
+ S3000
31
+ ].freeze
32
+
10
33
  private
11
34
 
12
- def initialize(caminho:, destino_dos_arquivos_data:, de_recibo_para_nome_do_arquivo_data:)
35
+ def initialize(empresa:, caminho:)
36
+ @empresa = empresa
13
37
  @caminho = caminho
14
- @destino_dos_arquivos_data = destino_dos_arquivos_data
15
- @de_recibo_para_nome_do_arquivo_data = de_recibo_para_nome_do_arquivo_data
16
38
  end
17
39
 
18
- attr_reader :caminho, :destino_dos_arquivos_data, :de_recibo_para_nome_do_arquivo_data
40
+ attr_reader :empresa, :caminho
19
41
 
20
42
  public
21
43
 
44
+ def processavel?
45
+ TIPOS_DE_EVENTO_PROCESSAVEIS.include?(tipo_de_evento)
46
+ end
47
+
48
+ def momento_de_processamento_pelo_e_social
49
+ # otimizacao do gerenciamento de memoria
50
+ carregar_conteudo
51
+ .then { |conteudo| Nokogiri::XML(conteudo) }
52
+ .then { |xml| Nokogiri::XML(xml.css('eSocial/retornoProcessamentoDownload/recibo/*').to_s) }
53
+ .then { |xml_do_recibo| XML.new(xml_do_recibo) }
54
+ .then { |recibo| recibo['retornoEvento/processamento/dhProcessamento'] }
55
+ end
56
+
22
57
  def nome
23
58
  @nome ||= File.basename(caminho, '.xml')
24
59
  end
25
60
 
26
61
  def processar
27
- return unless %w[S1000 S1005 S1010 S1020 S1030 S1040 S1050 S1070 S2190 S2200 S2205 S2206 S2230 S2250 S2300 S2306]
28
- .include?(tipo_de_evento)
29
-
62
+ Console.print "processando #{nome}.xml..."
30
63
  arquivo.processar
31
64
  end
32
65
 
33
66
  private
34
67
 
35
68
  def tipo_de_evento
36
- nome[-6..].delete('-')
37
- end
38
-
39
- def arquivo
40
- if evento_de_tabela?
41
- evento_de_tabela
42
- elsif evento_nao_periodico?
43
- evento_nao_periodico
44
- end
45
- end
46
-
47
- def evento_de_tabela?
48
- tipo_de_evento.start_with?('S10')
49
- end
50
-
51
- def evento_de_tabela
52
- classe_do_arquivo.new(
53
- xml_do_evento: xml_do_evento,
54
- xml_do_recibo: xml_do_recibo,
55
- destino_dos_arquivos_data: destino_dos_arquivos_data
56
- )
69
+ @tipo_de_evento ||= nome[-6..].delete('-')
57
70
  end
58
71
 
59
- def evento_nao_periodico?
60
- tipo_de_evento.start_with?('S2')
72
+ def carregar_conteudo
73
+ File.read(caminho)
61
74
  end
62
75
 
63
- def evento_nao_periodico
64
- classe_do_arquivo.new(
65
- xml_do_evento: xml_do_evento,
66
- xml_do_recibo: xml_do_recibo,
67
- destino_dos_arquivos_data: destino_dos_arquivos_data,
68
- de_recibo_para_nome_do_arquivo_data: de_recibo_para_nome_do_arquivo_data
69
- )
76
+ def arquivo
77
+ classe_do_arquivo.new(empresa: empresa, evento: evento, recibo: recibo)
70
78
  end
71
79
 
72
80
  def classe_do_arquivo
@@ -75,10 +83,10 @@ module Teodoro
75
83
 
76
84
  def modulo_do_leiaute
77
85
  {
78
- '02_04_01' => Leiaute_2_4_1,
79
- '02_04_02' => Leiaute_2_4_1, # FIXME: Tales
80
- '02_05_00' => Leiaute_2_4_1, # FIXME: Tales
81
- '01_00_00' => Leiaute_2_4_1 # FIXME: Tales
86
+ '02_04_01' => Leiaute_2,
87
+ '02_04_02' => Leiaute_2,
88
+ '02_05_00' => Leiaute_2,
89
+ '_S_01_00_00' => Leiaute_2 # FIXME: Tales
82
90
  }[versao_do_leiaute_no_xml]
83
91
  end
84
92
 
@@ -95,18 +103,19 @@ module Teodoro
95
103
  end
96
104
 
97
105
  def xml
98
- @xml ||= Nokogiri::XML(conteudo)
106
+ @xml ||= Nokogiri::XML(carregar_conteudo)
99
107
  end
100
108
 
101
- def conteudo
102
- File.read(caminho)
109
+ def evento
110
+ XML.new(xml_do_evento)
103
111
  end
104
112
 
105
- def xml_do_recibo
106
- Nokogiri::XML(xml.css('eSocial/retornoProcessamentoDownload/recibo/*').to_s)
113
+ def recibo
114
+ @recibo ||= XML.new(xml_do_recibo)
107
115
  end
108
116
 
109
- module Base
117
+ def xml_do_recibo
118
+ Nokogiri::XML(xml.css('eSocial/retornoProcessamentoDownload/recibo/*').to_s)
110
119
  end
111
120
  end
112
121
  end
@@ -1,9 +1,5 @@
1
1
  module Console
2
- class << self
3
- def print(*strings, color: nil)
4
- color_codes = { green: 32, red: 31 }
5
- strings = strings.map { |string| "\e[#{color_codes[color]}m#{string}\e[0m" } if color
6
- puts strings
7
- end
2
+ def self.print(string = nil)
3
+ Kernel.print "\r\e[2K#{string}"
8
4
  end
9
5
  end
@@ -20,14 +20,15 @@ module Teodoro
20
20
  criar_diretorio_dos_arquivos_xml
21
21
  descompactar_arquivos_de_origem
22
22
  criar_diretorio_dos_arquivos_data
23
+ ordenar_arquivos_xml
23
24
  processar_arquivos_xml
25
+ limpar_linha_de_feedback
24
26
  end
25
27
 
26
28
  private
27
29
 
28
30
  def dar_feedback_para_o_usuario
29
- puts ''
30
- Console.print nome_do_diretorio, color: :green
31
+ puts "\e[32m#{nome_do_diretorio}\e[0m" # green
31
32
  end
32
33
 
33
34
  def nome_do_diretorio
@@ -63,23 +64,55 @@ module Teodoro
63
64
  @destino_dos_arquivos_data ||= File.join(destino, 'data')
64
65
  end
65
66
 
67
+ def ordenar_arquivos_xml
68
+ Console.print 'ordenando os arquivos XML...'
69
+ arquivos_xml.sort_by! { [_1.momento_de_processamento_pelo_e_social, _1.nome] }
70
+ end
71
+
66
72
  def processar_arquivos_xml
67
- arquivos_xml.each(&:processar)
73
+ # otimizacao do gerenciamento de memoria
74
+ arquivos_xml.shift.processar while arquivos_xml.any?
68
75
  end
69
76
 
70
77
  def arquivos_xml
71
- Dir[File.join(destino_dos_arquivos_xml, '*.xml')]
72
- .map do |caminho|
73
- ArquivoXML.new(
74
- caminho: caminho,
75
- destino_dos_arquivos_data: destino_dos_arquivos_data,
76
- de_recibo_para_nome_do_arquivo_data: de_recibo_para_nome_do_arquivo_data
77
- )
78
- end
79
- end
80
-
81
- def de_recibo_para_nome_do_arquivo_data
82
- @de_recibo_para_nome_do_arquivo_data ||= {}
78
+ @arquivos_xml ||= Dir[File.join(destino_dos_arquivos_xml, '*.xml')]
79
+ .map { |caminho| ArquivoXML.new(empresa: empresa, caminho: caminho) }
80
+ .select(&:processavel?)
81
+ end
82
+
83
+ def empresa
84
+ @empresa ||= Obj.new(
85
+ destino_dos_arquivos_data: destino_dos_arquivos_data,
86
+ de_recibo_para_nome_do_arquivo_data: {},
87
+ admissoes_por_matricula: {},
88
+ contratos_de_trabalhador_sem_vinculo: ContratosDeTrabalhadorSemVinculo.new
89
+ )
90
+ end
91
+
92
+ def limpar_linha_de_feedback
93
+ Console.print
94
+ end
95
+
96
+ class ContratosDeTrabalhadorSemVinculo
97
+ def <<(contrato)
98
+ contratos << contrato
99
+ end
100
+
101
+ def [](cpf_do_trabalhador:, categoria_do_trabalhador:, data:)
102
+ contratos
103
+ .select {
104
+ [_1.cpf_do_trabalhador, _1.categoria_do_trabalhador] == [cpf_do_trabalhador, categoria_do_trabalhador]
105
+ }
106
+ .sort_by(&:data_de_inicio)
107
+ .reverse
108
+ .find { _1.data_de_inicio <= data }
109
+ end
110
+
111
+ private
112
+
113
+ def contratos
114
+ @contratos ||= []
115
+ end
83
116
  end
84
117
  end
85
118
  end