cnab240 0.0.17 → 0.1.0

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 (151) hide show
  1. checksums.yaml +7 -0
  2. data/cnab240.gemspec +2 -1
  3. data/lib/cnab240/arquivo/arquivo.rb +89 -60
  4. data/lib/cnab240/arquivo/builder.rb +162 -154
  5. data/lib/cnab240/arquivo/estrutura.rb +159 -95
  6. data/lib/cnab240/arquivo/lote.rb +57 -57
  7. data/lib/cnab240/arquivo/v40/header.rb +30 -30
  8. data/lib/cnab240/arquivo/v40/trailer.rb +11 -11
  9. data/lib/cnab240/arquivo/v80/header.rb +28 -27
  10. data/lib/cnab240/arquivo/v80/trailer.rb +11 -11
  11. data/lib/cnab240/arquivo/v83/header.rb +38 -0
  12. data/lib/cnab240/arquivo/v83/trailer.rb +17 -0
  13. data/lib/cnab240/arquivo/v86/header.rb +27 -28
  14. data/lib/cnab240/arquivo/v86/trailer.rb +12 -12
  15. data/lib/cnab240/arquivo/v87/header.rb +38 -0
  16. data/lib/cnab240/arquivo/v87/trailer.rb +18 -0
  17. data/lib/cnab240/ext/attribute_accessors.rb +2 -2
  18. data/lib/cnab240/ext/bindata.rb +9 -9
  19. data/lib/cnab240/ext/default_mixin.rb +11 -12
  20. data/lib/cnab240/ext/filler.rb +16 -16
  21. data/lib/cnab240/ext/lstring.rb +5 -5
  22. data/lib/cnab240/ext/segmento_mixin.rb +4 -4
  23. data/lib/cnab240/helper/helper.rb +15 -0
  24. data/lib/cnab240/helper/pagamento_bb.rb +51 -0
  25. data/lib/cnab240/helper/pagamento_bradesco.rb +49 -0
  26. data/lib/cnab240/helper/pagamento_itau.rb +34 -49
  27. data/lib/cnab240/helper/pagamento_sicoob.rb +55 -0
  28. data/lib/cnab240/pagamentos/v40/header.rb +35 -37
  29. data/lib/cnab240/pagamentos/v40/trailer.rb +13 -13
  30. data/lib/cnab240/pagamentos/v80/header.rb +45 -45
  31. data/lib/cnab240/pagamentos/v80/trailer.rb +13 -13
  32. data/lib/cnab240/pagamentos/v83/header.rb +45 -0
  33. data/lib/cnab240/pagamentos/v83/trailer.rb +18 -0
  34. data/lib/cnab240/pagamentos/v86/header.rb +44 -44
  35. data/lib/cnab240/pagamentos/v86/titulos/header.rb +44 -44
  36. data/lib/cnab240/pagamentos/v86/titulos/trailer.rb +14 -14
  37. data/lib/cnab240/pagamentos/v86/trailer.rb +14 -14
  38. data/lib/cnab240/pagamentos/v86/tributos/header.rb +45 -45
  39. data/lib/cnab240/pagamentos/v86/tributos/trailer.rb +12 -12
  40. data/lib/cnab240/pagamentos/v87/header.rb +46 -0
  41. data/lib/cnab240/pagamentos/v87/titulos/header.rb +46 -0
  42. data/lib/cnab240/pagamentos/v87/titulos/trailer.rb +18 -0
  43. data/lib/cnab240/pagamentos/v87/trailer.rb +18 -0
  44. data/lib/cnab240/pagamentos/v87/tributos/header.rb +47 -0
  45. data/lib/cnab240/pagamentos/v87/tributos/trailer.rb +17 -0
  46. data/lib/cnab240/segmentos/v40/segmento_a.rb +45 -48
  47. data/lib/cnab240/segmentos/v80/agencia_itau.rb +11 -12
  48. data/lib/cnab240/segmentos/v80/agencia_outros.rb +9 -10
  49. data/lib/cnab240/segmentos/v80/segmento_a.rb +59 -61
  50. data/lib/cnab240/segmentos/v83/segmento_a.rb +42 -0
  51. data/lib/cnab240/segmentos/v83/segmento_b.rb +40 -0
  52. data/lib/cnab240/segmentos/v83/segmento_j.rb +33 -0
  53. data/lib/cnab240/segmentos/v83/segmento_z.rb +19 -0
  54. data/lib/cnab240/segmentos/v86/segmento_a.rb +42 -45
  55. data/lib/cnab240/segmentos/v86/segmento_b.rb +38 -39
  56. data/lib/cnab240/segmentos/v86/segmento_c.rb +23 -24
  57. data/lib/cnab240/segmentos/v86/segmento_j.rb +25 -26
  58. data/lib/cnab240/segmentos/v86/segmento_j52.rb +22 -24
  59. data/lib/cnab240/segmentos/v86/segmento_n.rb +50 -51
  60. data/lib/cnab240/segmentos/v86/segmento_n1.rb +13 -15
  61. data/lib/cnab240/segmentos/v86/segmento_n2.rb +15 -17
  62. data/lib/cnab240/segmentos/v86/segmento_n3.rb +15 -17
  63. data/lib/cnab240/segmentos/v86/segmento_n4.rb +17 -19
  64. data/lib/cnab240/segmentos/v86/segmento_n5.rb +15 -17
  65. data/lib/cnab240/segmentos/v86/segmento_n6.rb +15 -17
  66. data/lib/cnab240/segmentos/v86/segmento_n7.rb +16 -18
  67. data/lib/cnab240/segmentos/v86/segmento_n8.rb +15 -18
  68. data/lib/cnab240/segmentos/v86/segmento_o.rb +20 -21
  69. data/lib/cnab240/segmentos/v86/segmento_w.rb +16 -17
  70. data/lib/cnab240/segmentos/v86/segmento_w1.rb +12 -13
  71. data/lib/cnab240/segmentos/v86/segmento_z.rb +14 -14
  72. data/lib/cnab240/segmentos/v87/segmento_a.rb +44 -0
  73. data/lib/cnab240/segmentos/v87/segmento_b.rb +40 -0
  74. data/lib/cnab240/segmentos/v87/segmento_c.rb +32 -0
  75. data/lib/cnab240/segmentos/v87/segmento_j.rb +33 -0
  76. data/lib/cnab240/segmentos/v87/segmento_j52.rb +32 -0
  77. data/lib/cnab240/segmentos/v87/segmento_n.rb +59 -0
  78. data/lib/cnab240/segmentos/v87/segmento_n1.rb +19 -0
  79. data/lib/cnab240/segmentos/v87/segmento_n2.rb +21 -0
  80. data/lib/cnab240/segmentos/v87/segmento_n3.rb +21 -0
  81. data/lib/cnab240/segmentos/v87/segmento_n4.rb +23 -0
  82. data/lib/cnab240/segmentos/v87/segmento_n5.rb +21 -0
  83. data/lib/cnab240/segmentos/v87/segmento_n6.rb +21 -0
  84. data/lib/cnab240/segmentos/v87/segmento_n7.rb +21 -0
  85. data/lib/cnab240/segmentos/v87/segmento_n8.rb +22 -0
  86. data/lib/cnab240/segmentos/v87/segmento_o.rb +27 -0
  87. data/lib/cnab240/segmentos/v87/segmento_w.rb +24 -0
  88. data/lib/cnab240/segmentos/v87/segmento_w1.rb +16 -0
  89. data/lib/cnab240/segmentos/v87/segmento_z.rb +19 -0
  90. data/lib/cnab240/version.rb +1 -2
  91. data/lib/cnab240.rb +54 -24
  92. metadata +64 -133
  93. data/.gitignore +0 -19
  94. data/.rspec +0 -2
  95. data/.travis.yml +0 -4
  96. data/Gemfile +0 -6
  97. data/LICENSE +0 -22
  98. data/README.md +0 -135
  99. data/docs/vendor/febraban/subcpadr12_layout_padrao_V86.pdf +0 -0
  100. data/docs/vendor/itau/SISPAG_CNAB_240.pdf +0 -0
  101. data/docs/vendor/itau/sisdeb_cnab_240.pdf +0 -0
  102. data/spec/arquivo/arquivo_spec.rb +0 -95
  103. data/spec/arquivo/v40/header_spec.rb +0 -68
  104. data/spec/arquivo/v40/trailer_spec.rb +0 -25
  105. data/spec/arquivo/v80/header_spec.rb +0 -60
  106. data/spec/arquivo/v80/trailer_spec.rb +0 -26
  107. data/spec/arquivo/v86/header_spec.rb +0 -89
  108. data/spec/arquivo/v86/trailer_spec.rb +0 -27
  109. data/spec/bindata/bindata_spec.rb +0 -55
  110. data/spec/cnab240_spec.rb +0 -22
  111. data/spec/helper/pagamento_itau_spec.rb +0 -83
  112. data/spec/hom/hom_spec.rb +0 -65
  113. data/spec/hom/retorno/SB22112AIT.RET +0 -5
  114. data/spec/hom/retorno/SB23112AIT.RET +0 -5
  115. data/spec/pagamentos/v40/header_spec.rb +0 -59
  116. data/spec/pagamentos/v40/lote_spec.rb +0 -25
  117. data/spec/pagamentos/v40/trailer_spec.rb +0 -28
  118. data/spec/pagamentos/v80/header_spec.rb +0 -52
  119. data/spec/pagamentos/v80/lote_spec.rb +0 -25
  120. data/spec/pagamentos/v80/trailer_spec.rb +0 -28
  121. data/spec/pagamentos/v86/header_spec.rb +0 -53
  122. data/spec/pagamentos/v86/lote_spec.rb +0 -38
  123. data/spec/pagamentos/v86/titulos/header_spec.rb +0 -51
  124. data/spec/pagamentos/v86/titulos/lote_spec.rb +0 -37
  125. data/spec/pagamentos/v86/titulos/trailer_spec.rb +0 -30
  126. data/spec/pagamentos/v86/trailer_spec.rb +0 -30
  127. data/spec/pagamentos/v86/tributos/header_spec.rb +0 -53
  128. data/spec/pagamentos/v86/tributos/lote_spec.rb +0 -43
  129. data/spec/pagamentos/v86/tributos/trailer_spec.rb +0 -27
  130. data/spec/segmentos/v40/segmento_a_spec.rb +0 -70
  131. data/spec/segmentos/v80/segmento_a_spec.rb +0 -70
  132. data/spec/segmentos/v86/segmento_a_spec.rb +0 -65
  133. data/spec/segmentos/v86/segmento_b_spec.rb +0 -67
  134. data/spec/segmentos/v86/segmento_c_spec.rb +0 -51
  135. data/spec/segmentos/v86/segmento_j52_spec.rb +0 -55
  136. data/spec/segmentos/v86/segmento_j_spec.rb +0 -55
  137. data/spec/segmentos/v86/segmento_n1_spec.rb +0 -43
  138. data/spec/segmentos/v86/segmento_n2_spec.rb +0 -46
  139. data/spec/segmentos/v86/segmento_n3_spec.rb +0 -45
  140. data/spec/segmentos/v86/segmento_n4_spec.rb +0 -47
  141. data/spec/segmentos/v86/segmento_n5_spec.rb +0 -45
  142. data/spec/segmentos/v86/segmento_n6_spec.rb +0 -45
  143. data/spec/segmentos/v86/segmento_n7_spec.rb +0 -46
  144. data/spec/segmentos/v86/segmento_n8_spec.rb +0 -45
  145. data/spec/segmentos/v86/segmento_n_spec.rb +0 -73
  146. data/spec/segmentos/v86/segmento_o_spec.rb +0 -50
  147. data/spec/segmentos/v86/segmento_spec.rb +0 -12
  148. data/spec/segmentos/v86/segmento_w_spec.rb +0 -51
  149. data/spec/segmentos/v86/segmento_z_spec.rb +0 -42
  150. data/spec/spec_helper.rb +0 -10
  151. data/spec/tmp/.gitkeep +0 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f7abc2f60eafc559fb95f0efd7875b96426b2faf
4
+ data.tar.gz: d07c23e2e17044cde19afd54237cd44ce7d0ad3d
5
+ SHA512:
6
+ metadata.gz: a44d8711e5af6c8b68f49c2bb63f8112e9b01a4103c7b53fd825f9f68f8d969af0a99ce97d16331dba6ea30d93081a93ac5ce5151a0c2222163b94034689353c
7
+ data.tar.gz: e5c9c0ab4916bee2193c2e330b781df9388dc5421ebbdd02c03bd74ed755e981de60f42aca0ce405e7d21d38b1beb289555804a8c2fb535982e2427d90ab9339
data/cnab240.gemspec CHANGED
@@ -3,6 +3,7 @@ require File.expand_path('../lib/cnab240/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
5
  gem.add_development_dependency "rspec"
6
+ gem.add_development_dependency "debugger"
6
7
  gem.add_dependency "bindata"
7
8
 
8
9
  gem.authors = ["Eduardo Mourao"]
@@ -13,7 +14,7 @@ Gem::Specification.new do |gem|
13
14
 
14
15
  gem.rubyforge_project = "cnab240"
15
16
 
16
- gem.files = `git ls-files`.split($\)
17
+ gem.files = Dir.glob('lib/**/*') + ['Rakefile'] + ['cnab240.gemspec']
17
18
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
19
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
20
  gem.name = "cnab240"
@@ -1,61 +1,90 @@
1
1
  module Cnab240::Arquivo
2
- class Arquivo
3
-
4
- attr_accessor :header
5
- attr_accessor :lotes
6
- attr_accessor :trailer
7
- attr_accessor :versao
8
-
9
- def initialize(versao = "V86")
10
- @versao = versao
11
- @header = eval("Cnab240::#{versao}::Arquivo::Header").new
12
- @trailer = eval("Cnab240::#{versao}::Arquivo::Trailer").new
13
- @lotes = []
14
- end
15
-
16
- def linhas
17
- self.auto_fill if Cnab240.auto_fill_enabled
18
- a = []
19
- a << @header.linha
20
- @lotes.each do |lote|
21
- lote.linhas.each do |linha|
22
- a << linha
23
- end
24
- end
25
- a << @trailer.linha
26
- a
27
- end
28
-
29
- def <<(lote)
30
- lote.arquivo = self
31
- @lotes << lote
32
- end
33
-
34
- def string
35
- linhas.join("\r\n") << "\r\n"
36
- end
37
-
38
- def save_to_file(filename)
39
- begin
40
- File.delete(filename) # LoL
41
- rescue
42
- end
43
- File.open(filename, 'w') {|f| f.write(string) }
44
- end
45
-
46
- def self.load_from_file(filename)
47
- Cnab240::Builder.new(filename).arquivos
48
- end
49
-
50
-
51
- def auto_fill
52
- trailer.totais_qtde_lotes = lotes.length.to_s
53
- qtd_registros = lotes.length * 2 # header e trailer de cada lote
54
- lotes.each { |l| qtd_registros += l.segmentos.length } # segmentos
55
- qtd_registros += 2 # header e trailer de arquivo
56
- trailer.totais_qtde_registros = qtd_registros.to_s
57
- end
58
-
59
- end
60
-
61
- end
2
+ class Arquivo
3
+
4
+ attr_accessor :header
5
+ attr_accessor :lotes
6
+ attr_accessor :trailer
7
+ attr_accessor :versao
8
+
9
+ def initialize(versao = "V86")
10
+ @versao = versao
11
+ @header = eval("Cnab240::#{versao}::Arquivo::Header").new
12
+ @trailer = eval("Cnab240::#{versao}::Arquivo::Trailer").new
13
+ @lotes = []
14
+ end
15
+
16
+ def linhas
17
+ self.auto_fill if Cnab240.auto_fill_enabled
18
+ a = []
19
+ a << @header.linha
20
+ @lotes.each do |lote|
21
+ lote.linhas.each do |linha|
22
+ a << linha
23
+ end
24
+ end
25
+ a << @trailer.linha
26
+ a
27
+ end
28
+
29
+ def <<(lote)
30
+ lote.arquivo = self
31
+ @lotes << lote
32
+ end
33
+
34
+ def string
35
+ linhas.join("\r\n") << "\r\n"
36
+ end
37
+
38
+ # Writes +Cnab240::Arquivo::Arquivo+ contents into a +File+, overwriting its current contents.
39
+ #
40
+ # @example Save contents to a file.
41
+ # Cnab240::Arquivo::Arquivo.new.save_to_file('/tmp/cnab240.txt')
42
+ #
43
+ # @param [ String ] filename The file name to which the contents will be saved to.
44
+ #
45
+ # @return [ Integer ] The number of bytes written to the file.
46
+ #
47
+ # @since 0.0.20
48
+ def save_to_file(filename)
49
+ File.open(filename, 'w'){|f| f.write(string)}
50
+ end
51
+
52
+ # Loads contents from a +File+ into +Cnab240::Arquivo::Arquivo+ instances.
53
+ #
54
+ # @example Load contents from a file.
55
+ # Cnab240::Arquivo::Arquivo.load_from_file('/tmp/cnab240.txt')
56
+ #
57
+ # @param [ String ] filename The file name from which the contents will be read.
58
+ #
59
+ # @return [ Array<Cnab240::Arquivo::Arquivo> ] A list of +Cnab240::Arquivo::Arquivo+ instances representing the contents read.
60
+ #
61
+ # @since 0.0.20
62
+ def self.load_from_file(filename)
63
+ load(File.open(filename, 'r'))
64
+ end
65
+
66
+ # Loads contents from an object that implements the +IO+ interface into +Cnab240::Arquivo::Arquivo+ instances.
67
+ #
68
+ # @example Load contents from a file.
69
+ # Cnab240::Arquivo::Arquivo.load_from_file(File.open('/tmp/cnab240.txt', 'r'))
70
+ #
71
+ # @param [ IO ] file The I/O interface from which the contents will be read.
72
+ #
73
+ # @return [ Array<Cnab240::Arquivo::Arquivo> ] A list of +Cnab240::Arquivo::Arquivo+ instances representing the contents read.
74
+ #
75
+ # @since 0.0.20
76
+ def self.load(io)
77
+ Cnab240::Builder.new(io).arquivos
78
+ end
79
+
80
+ def auto_fill
81
+ trailer.totais_qtde_lotes = lotes.length.to_s
82
+ qtd_registros = lotes.length * 2 # header e trailer de cada lote
83
+ lotes.each { |l| qtd_registros += l.segmentos.length } # segmentos
84
+ qtd_registros += 2 # header e trailer de arquivo
85
+ trailer.totais_qtde_registros = qtd_registros.to_s
86
+ end
87
+
88
+ end
89
+
90
+ end
@@ -1,156 +1,164 @@
1
1
  module Cnab240
2
- class Builder
3
-
4
- HEADER_ARQUIVO = '0'
5
- HEADER_LOTE = '1'
6
- INICIAIS_LOTE = '2'
7
- DETALHE = '3'
8
- FINAIS_LOTE = '4'
9
- TRAILER_LOTE = '5'
10
- TRAILER_ARQUIVO = '9'
11
-
12
- RANGE_TIPO_REGISTRO = 7..7
13
- RANGE_LAYOUT_ARQUIVO = 163..165
14
- RANGE_HEADER_LOTE = 13..15
15
- RANGE_TIPO_OPERACAO_DETALHE = 13..13
16
-
17
- attr_accessor :arquivos
18
-
19
- def initialize(filename = nil)
20
- load_from_file(filename) unless filename.nil?
21
- end
22
-
23
- def load_from_file(filename)
24
- @arquivos = []
25
- line_number = 0
26
- File.open(filename, "r").each_line do |line|
27
- check_line_encoding line, ++line_number
28
- case line[RANGE_TIPO_REGISTRO]
29
-
30
- when HEADER_ARQUIVO
31
- find_header_arquivo line, line_number
32
-
33
- when HEADER_LOTE
34
- find_header_lote line, line_number
35
-
36
- when INICIAIS_LOTE
37
- raise NotImplementedError.new("Tipo de registro nao suportado")
38
-
39
- when DETALHE
40
- find_segmento line, line_number
41
-
42
- when FINAIS_LOTE
43
- raise NotImplementedError.new("Tipo de registro not implemented")
44
-
45
- when TRAILER_LOTE
46
- arquivos.last.lotes.last.trailer.read(line)
47
-
48
- when TRAILER_ARQUIVO
49
- arquivos.last.trailer = Trailer.read(line)
50
-
51
- else
52
- raise "Invalid tipo de registro: #{line[RANGE_TIPO_REGISTRO]} at line #{line_number} \n\t Line: [#{line}]"
53
- end
54
- end
55
- arquivos
56
- end
57
-
58
- private
59
-
60
- def check_line_encoding(line, line_number = -1)
61
- line = line.force_encoding("US-ASCII").encode("UTF-8", :invalid=>:replace) if line.respond_to?(:force_encoding)
62
- line.gsub!("\r", "")
63
- line.gsub!("\n", "")
64
- raise "Invalid line length: #{line.length} expected 240 at line number #{line_number}\n\t Line: [#{line}]" unless line.length == 240
65
- line
66
- end
67
-
68
- def find_header_arquivo(line, line_number = -1)
69
- arquivos << Cnab240::Arquivo::Arquivo.new
70
- case line[RANGE_LAYOUT_ARQUIVO]
71
- # when '080'
72
- # arquivos.last.versao = 'V80'
73
- # arquivos.last.header = Cnab240::V80::Arquivo::Header.read(line)
74
- when '085'
75
- arquivos.last.versao = 'V86'
76
- arquivos.last.header = Cnab240::V86::Arquivo::Header.read(line)
77
- when '040'
78
- arquivos.last.versao = 'V40'
79
- arquivos.last.header = Cnab240::V40::Arquivo::Header.read(line)
80
- when '000' # possivelmente V80 do itau
81
- if line[14..16] == '080'
82
- arquivos.last.versao = 'V80'
83
- arquivos.last.header = Cnab240::V80::Arquivo::Header.read(line)
84
- else
85
- raise "Versao de arquivo nao suportado: #{line[RANGE_LAYOUT_ARQUIVO]} na linha #{line_number}" if Cnab240.fallback == false
86
- arquivos.last.versao = 'V86'
87
- arquivos.last.header = Cnab240::V86::Arquivo::Header.read(line)
88
- end
89
- else
90
- raise "Versao de arquivo nao suportado: #{line[RANGE_LAYOUT_ARQUIVO]} na linha #{line_number}" if Cnab240.fallback == false
91
- arquivos.last.versao = 'V86'
92
- arquivos.last.header = Cnab240::V86::Arquivo::Header.read(line)
93
- end
94
- end
95
-
96
- def find_header_lote(line, line_number = -1)
97
- case line[RANGE_HEADER_LOTE]
98
- when '080'
99
- arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento, :tipo => :none, :versao => 'V80') do |l|
100
- l.header = Cnab240::V80::Pagamentos::Header.read(line)
101
- end
102
- when '030'
103
- case arquivos.last.versao
104
- when 'V80'
105
- arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento, :tipo => :none) do |l|
106
- l.header = Cnab240::V80::Pagamentos::Header.read(line)
107
- end
108
- when 'V40'
109
- arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento, :tipo => :none) do |l|
110
- l.header = Cnab240::V40::Pagamentos::Header.read(line)
111
- end
112
- else
113
- raise "Header de lote nao suportado para a versao de arquivo."
114
- end
115
- when '044'
116
- arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento, :tipo => :none) do |l|
117
- l.header = Cnab240::V86::Pagamentos::Header.read(line)
118
- end
119
- when '040'
120
- case arquivos.last.versao
121
- when 'V80'
122
- arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento, :tipo => :none) do |l|
123
- l.header = Cnab240::V80::Pagamentos::Header.read(line)
124
- end
125
- when 'V86'
126
- arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento_titulo_cobranca, :tipo => :none) do |l|
127
- l.header = Cnab240::V86::PagamentosTitulos::Header.read(line)
128
- end
129
- else
130
- raise "Header de lote nao suportado para a versao de arquivo."
131
- end
132
- when '011'
133
- arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento_titulo_tributos, :tipo => :none) do |l|
134
- l.header = Cnab240::V86::PagamentosTributos::Header.read(line)
135
- end
136
- else
137
- raise "Tipo de lote nao suportado: #{line[RANGE_HEADER_LOTE]} na linha #{line_number}"
138
- end
139
- end
140
-
141
- def find_segmento(line, line_number = -1)
142
- raise "Invalid segmento de lote: #{line[RANGE_TIPO_OPERACAO_DETALHE]} at line #{line_number}" unless ESTRUTURA[arquivos.last.versao][:segmentos_implementados].include? line[RANGE_TIPO_OPERACAO_DETALHE].downcase.intern
143
- case line[RANGE_TIPO_OPERACAO_DETALHE]
144
- when 'J'
145
- if line[17..18] == '52'
146
- arquivos.last.lotes.last.read_segmento('J52', line)
147
- else
148
- arquivos.last.lotes.last.read_segmento('J', line)
149
- end
150
- else
151
- arquivos.last.lotes.last.read_segmento(line[RANGE_TIPO_OPERACAO_DETALHE], line)
152
- end
153
- end
154
-
155
- end
2
+ class Builder
3
+
4
+ HEADER_ARQUIVO = '0'
5
+ HEADER_LOTE = '1'
6
+ INICIAIS_LOTE = '2'
7
+ DETALHE = '3'
8
+ FINAIS_LOTE = '4'
9
+ TRAILER_LOTE = '5'
10
+ TRAILER_ARQUIVO = '9'
11
+
12
+ RANGE_TIPO_REGISTRO = 7..7
13
+ RANGE_LAYOUT_ARQUIVO = 163..165
14
+ RANGE_HEADER_LOTE = 13..15
15
+ RANGE_TIPO_OPERACAO_DETALHE = 13..13
16
+
17
+ attr_accessor :arquivos
18
+
19
+ def initialize(io = nil)
20
+ load(io) unless io.nil?
21
+ end
22
+
23
+ def load(io)
24
+ @arquivos = []
25
+ line_number = 0
26
+ io.each_line do |line|
27
+ check_line_encoding line, ++line_number
28
+ case line[RANGE_TIPO_REGISTRO]
29
+
30
+ when HEADER_ARQUIVO
31
+ find_header_arquivo line, line_number
32
+
33
+ when HEADER_LOTE
34
+ find_header_lote line, line_number
35
+
36
+ when INICIAIS_LOTE
37
+ raise NotImplementedError.new("Tipo de registro nao suportado")
38
+
39
+ when DETALHE
40
+ find_segmento line, line_number
41
+
42
+ when FINAIS_LOTE
43
+ raise NotImplementedError.new("Tipo de registro not implemented")
44
+
45
+ when TRAILER_LOTE
46
+ arquivos.last.lotes.last.trailer.read(line)
47
+
48
+ when TRAILER_ARQUIVO
49
+ arquivos.last.trailer.read(line)
50
+
51
+ else
52
+ raise "Invalid tipo de registro: #{line[RANGE_TIPO_REGISTRO]} at line #{line_number} \n\t Line: [#{line}]"
53
+ end
54
+ end
55
+ arquivos
56
+ end
57
+
58
+ private
59
+
60
+ def check_line_encoding(line, line_number = -1)
61
+ line = line.force_encoding("US-ASCII").encode("UTF-8", :invalid => :replace) if line.respond_to?(:force_encoding)
62
+ line.gsub!("\r", "")
63
+ line.gsub!("\n", "")
64
+ raise "Invalid line length: #{line.length} expected 240 at line number #{line_number}\n\t Line: [#{line}]" unless line.length == 240
65
+ line
66
+ end
67
+
68
+ def find_header_arquivo(line, line_number = -1)
69
+ arquivos << Cnab240::Arquivo::Arquivo.new
70
+ case line[RANGE_LAYOUT_ARQUIVO]
71
+ when '087'
72
+ arquivos.last.versao = 'V87'
73
+ arquivos.last.header = Cnab240::V87::Arquivo::Header.read(line)
74
+ when '085'
75
+ arquivos.last.versao = 'V86'
76
+ arquivos.last.header = Cnab240::V86::Arquivo::Header.read(line)
77
+ when '040'
78
+ arquivos.last.versao = 'V40'
79
+ arquivos.last.header = Cnab240::V40::Arquivo::Header.read(line)
80
+ when '000' # possivelmente V80 do itau
81
+ if line[14..16] == '080'
82
+ arquivos.last.versao = 'V80'
83
+ arquivos.last.header = Cnab240::V80::Arquivo::Header.read(line)
84
+ else
85
+ raise "Versao de arquivo nao suportado: #{line[RANGE_LAYOUT_ARQUIVO]} na linha #{line_number}" if Cnab240.fallback == false
86
+ arquivos.last.versao = 'V86'
87
+ arquivos.last.header = Cnab240::V86::Arquivo::Header.read(line)
88
+ end
89
+ else
90
+ raise "Versao de arquivo nao suportado: #{line[RANGE_LAYOUT_ARQUIVO]} na linha #{line_number}" if Cnab240.fallback == false
91
+ arquivos.last.versao = 'V86'
92
+ arquivos.last.header = Cnab240::V86::Arquivo::Header.read(line)
93
+ end
94
+ end
95
+
96
+ def find_header_lote(line, line_number = -1)
97
+ case line[RANGE_HEADER_LOTE]
98
+ when '080'
99
+ arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento, :tipo => :none, :versao => 'V80') do |l|
100
+ l.header = Cnab240::V80::Pagamentos::Header.read(line)
101
+ end
102
+ when '030'
103
+ case arquivos.last.versao
104
+ when 'V80'
105
+ arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento, :tipo => :none) do |l|
106
+ l.header = Cnab240::V80::Pagamentos::Header.read(line)
107
+ end
108
+ when 'V40'
109
+ arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento, :tipo => :none) do |l|
110
+ l.header = Cnab240::V40::Pagamentos::Header.read(line)
111
+ end
112
+ else
113
+ raise "Header de lote nao suportado para a versao de arquivo."
114
+ end
115
+ when '045'
116
+ arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento, :tipo => :none) do |l|
117
+ l.header = Cnab240::V87::Pagamentos::Header.read(line)
118
+ end
119
+ when '044'
120
+ arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento, :tipo => :none) do |l|
121
+ l.header = Cnab240::V86::Pagamentos::Header.read(line)
122
+ end
123
+ when '040'
124
+ case arquivos.last.versao
125
+ when 'V80'
126
+ arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento, :tipo => :none) do |l|
127
+ l.header = Cnab240::V80::Pagamentos::Header.read(line)
128
+ end
129
+ when 'V86'
130
+ arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento_titulo_cobranca, :tipo => :none) do |l|
131
+ l.header = Cnab240::V86::PagamentosTitulos::Header.read(line)
132
+ end
133
+ when 'V87'
134
+ arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento_titulo_cobranca, :tipo => :none) do |l|
135
+ l.header = Cnab240::V87::PagamentosTitulos::Header.read(line)
136
+ end
137
+ else
138
+ raise "Header de lote nao suportado para a versao de arquivo."
139
+ end
140
+ when '011'
141
+ arquivos.last.lotes << Cnab240::Lote.new(:operacao => :pagamento_titulo_tributos, :tipo => :none) do |l|
142
+ l.header = Cnab240::V86::PagamentosTributos::Header.read(line)
143
+ end
144
+ else
145
+ raise "Tipo de lote nao suportado: #{line[RANGE_HEADER_LOTE]} na linha #{line_number}"
146
+ end
147
+ end
148
+
149
+ def find_segmento(line, line_number = -1)
150
+ raise "Invalid segmento de lote: #{line[RANGE_TIPO_OPERACAO_DETALHE]} at line #{line_number}" unless ESTRUTURA[arquivos.last.versao][:segmentos_implementados].include? line[RANGE_TIPO_OPERACAO_DETALHE].downcase.intern
151
+ case line[RANGE_TIPO_OPERACAO_DETALHE]
152
+ when 'J'
153
+ if line[17..18] == '52'
154
+ arquivos.last.lotes.last.read_segmento('J52', line)
155
+ else
156
+ arquivos.last.lotes.last.read_segmento('J', line)
157
+ end
158
+ else
159
+ arquivos.last.lotes.last.read_segmento(line[RANGE_TIPO_OPERACAO_DETALHE], line)
160
+ end
161
+ end
162
+
163
+ end
156
164
  end