zilverline-mt940 1.0 → 2.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 (52) hide show
  1. checksums.yaml +8 -8
  2. data/Gemfile.lock +1 -1
  3. data/README.md +5 -4
  4. data/lib/mt940.rb +1 -6
  5. data/lib/mt940/version.rb +2 -2
  6. data/lib/mt940_structured/file_content.rb +46 -0
  7. data/lib/mt940_structured/header.rb +30 -0
  8. data/lib/mt940_structured/mt940_structured.rb +8 -0
  9. data/lib/mt940_structured/parser.rb +18 -0
  10. data/lib/mt940_structured/parsers/abnamro/abnamro.rb +5 -0
  11. data/lib/mt940_structured/parsers/abnamro/parser.rb +15 -0
  12. data/lib/mt940_structured/parsers/abnamro/transaction_parser.rb +55 -0
  13. data/lib/mt940_structured/parsers/balance_parser.rb +12 -0
  14. data/lib/mt940_structured/parsers/bank_statement_parser.rb +59 -0
  15. data/lib/mt940_structured/parsers/base.rb +34 -0
  16. data/lib/mt940_structured/parsers/date_parser.rb +7 -0
  17. data/lib/mt940_structured/parsers/default_line61_parser.rb +25 -0
  18. data/lib/mt940_structured/parsers/iban_support.rb +15 -0
  19. data/lib/mt940_structured/parsers/ing/ing.rb +7 -0
  20. data/lib/mt940_structured/parsers/ing/parser.rb +18 -0
  21. data/lib/mt940_structured/parsers/ing/structured_transaction_parser.rb +50 -0
  22. data/lib/mt940_structured/parsers/ing/transaction_parser.rb +31 -0
  23. data/lib/mt940_structured/parsers/ing/types.rb +26 -0
  24. data/lib/mt940_structured/parsers/parsers.rb +16 -0
  25. data/lib/mt940_structured/parsers/rabobank/parser.rb +13 -0
  26. data/lib/mt940_structured/parsers/rabobank/rabobank.rb +8 -0
  27. data/lib/mt940_structured/parsers/rabobank/structured_transaction_parser.rb +41 -0
  28. data/lib/mt940_structured/parsers/rabobank/transaction_parser.rb +29 -0
  29. data/lib/mt940_structured/parsers/rabobank/types.rb +714 -0
  30. data/lib/mt940_structured/parsers/structured_description_parser.rb +12 -0
  31. data/lib/mt940_structured/parsers/tridios/parser.rb +14 -0
  32. data/lib/mt940_structured/parsers/tridios/transaction_parser.rb +23 -0
  33. data/lib/mt940_structured/parsers/tridios/triodos.rb +5 -0
  34. data/spec/fixtures/ing/eu_incasso.txt +17 -0
  35. data/spec/fixtures/ing/eu_incasso_foreign_transaction.txt +17 -0
  36. data/spec/fixtures/ing/failing.txt +18 -0
  37. data/spec/mt940_abnamro_spec.rb +18 -6
  38. data/spec/mt940_ing_spec.rb +78 -2
  39. data/spec/mt940_rabobank_spec.rb +11 -11
  40. data/spec/mt940_structured/file_content_spec.rb +77 -0
  41. data/spec/mt940_structured/header_spec.rb +32 -0
  42. data/spec/mt940_structured/parsers/rabobank/bank_statement_parser_spec.rb +32 -0
  43. data/spec/mt940_triodos_spec.rb +1 -1
  44. data/spec/mt940_two_accounts_spec.rb +1 -1
  45. metadata +41 -9
  46. data/lib/mt940/banks/abnamro.rb +0 -76
  47. data/lib/mt940/banks/ing.rb +0 -84
  48. data/lib/mt940/banks/rabobank.rb +0 -770
  49. data/lib/mt940/banks/triodos.rb +0 -20
  50. data/lib/mt940/base.rb +0 -165
  51. data/lib/mt940/structured_format.rb +0 -16
  52. data/spec/mt940_base_spec.rb +0 -48
@@ -1,20 +0,0 @@
1
- class MT940::Triodos < MT940::Base
2
-
3
- def self.determine_bank(*args)
4
- self if args[0].match(/^:20:/) && args[1] && args[1].match(/^:25:TRIODOSBANK/)
5
- end
6
-
7
- def parse_tag_86
8
- if !@tag86 && @line.match(/^:86:\s?(.*)\Z/m)
9
- @tag86 = true
10
- temp_description = $1.gsub(/\n/, ' ').gsub(/>\d{2}/, '').strip
11
- if temp_description.match(/^\d+(\d{9})(.*)$/)
12
- @transaction.contra_account = $1.rjust(9, '000000000')
13
- @transaction.description = $2.strip
14
- else
15
- @transaction.description = temp_description
16
- end
17
- end
18
- end
19
-
20
- end
@@ -1,165 +0,0 @@
1
- module MT940
2
-
3
- class Base
4
-
5
- MT_940_TAG_LINE = /^:(\d{2}(F|C)?):/
6
-
7
- attr_accessor :bank, :opening_balance, :opening_date
8
-
9
- def self.parse_mt940(file)
10
- file = File.open(file) if file.is_a?(String)
11
- if file.is_a?(File) || file.is_a?(Tempfile)
12
- first_line = file.readline
13
- second_line = file.readline unless file.eof?
14
- klass = determine_bank(first_line, second_line)
15
- file.rewind
16
- instance = klass.new(file)
17
- file.close
18
- instance.parse
19
- else
20
- raise ArgumentError.new('No file is given!')
21
- end
22
- end
23
-
24
- def parse
25
- @tag86 = false
26
- @lines.each do |line|
27
- @line = line
28
- @line.match(MT_940_TAG_LINE) ? send("parse_tag_#{$1}".to_sym) : parse_line
29
- end
30
- @bank_statements
31
- end
32
-
33
- protected
34
- def parse_description_after_tag(description_parts, tag)
35
- description_start_index = description_parts.index { |part| part == tag }
36
- if description_start_index
37
- description_parts[description_start_index + 1].gsub(/\r|\n/, '')
38
- else
39
- ''
40
- end
41
- end
42
-
43
-
44
- private
45
-
46
- def self.determine_bank(*args)
47
- Dir.foreach(File.dirname(__FILE__) + '/banks/') do |file|
48
- if file.match(/\.rb$/)
49
- klass = eval(file.gsub(/\.rb$/, '').capitalize)
50
- bank = klass.determine_bank(*args)
51
- return bank if bank
52
- end
53
- end
54
- self
55
- end
56
-
57
- def initialize(file)
58
- @bank_statements = {}
59
- @transactions = []
60
- @bank = self.class.to_s.split('::').last
61
- @bank = 'Unknown' if @bank == 'Base'
62
- temp_lines = file.readlines
63
- @lines = []
64
- index_of_temp_lines = 0
65
- index_in_lines = 0
66
- while index_of_temp_lines < temp_lines.size do
67
- line = temp_lines[index_of_temp_lines].encode('UTF-8', 'binary', :invalid => :replace, :undef => :replace) # remove invalid chars
68
- if mt_940_start_line?(line)
69
- @lines << line
70
- index_in_lines+=1
71
- else
72
- @lines[index_in_lines-1] += line
73
- end
74
- index_of_temp_lines+=1
75
- end
76
- end
77
-
78
- def mt_940_start_line?(line)
79
- line.match /^:?\d{2}(\D?|\d?):?.*$/
80
- end
81
-
82
- def parse_tag_25
83
- @line.gsub!('.', '')
84
- case @line
85
- when /^:\d{2}:NL/
86
- @bank_account_iban = @line[4, 18]
87
- @bank_account = @bank_account_iban.strip.split(//).last(10).join.sub(/^[0]*/,"")
88
- @is_structured_format = true
89
- when /^:\d{2}:\D*(\d*)/
90
- @bank_account = $1.gsub(/\D/, '').gsub(/^0+/, '')
91
- @is_structured_format = false
92
- else
93
- raise "Unknown format for tag 25: #{@line}"
94
- end
95
- @bank_statements[@bank_account] ||= []
96
- @tag86 = false
97
- end
98
-
99
- def parse_tag_28
100
- @bank_statement = BankStatement.new([], @bank_account, @bank_account_iban, 0, nil, nil)
101
- @bank_statements[@bank_account] << @bank_statement
102
- end
103
-
104
- alias_method :parse_tag_28C, :parse_tag_28
105
-
106
- def parse_tag_60F
107
- @currency = @line[12..14]
108
- balance_date = parse_date(@line[6..11])
109
-
110
- type = @line[5] == 'D' ? -1 : 1
111
- amount = @line[15..-1].gsub(",", ".").to_f * type
112
- @bank_statement.previous_balance = Balance.new(amount, balance_date, @currency)
113
- end
114
-
115
- def parse_tag_62F
116
- @currency = @line[12..14]
117
- balance_date = parse_date(@line[6..11])
118
-
119
- type = @line[5] == 'D' ? -1 : 1
120
- amount = @line[15..-1].gsub(",", ".").to_f * type
121
-
122
- @bank_statement.new_balance = Balance.new(amount, balance_date, @currency)
123
- @tag86 = false
124
- end
125
-
126
- def parse_tag_61
127
- if @line.match(/^:61:(\d{6})(C|D)(\d+),(\d{0,2})/)
128
- type = $2 == 'D' ? -1 : 1
129
- @transaction = MT940::Transaction.new(:bank_account => @bank_account, :amount => type * ($3 + '.' + $4).to_f, :bank => @bank, :currency => @currency)
130
- @transaction.date = parse_date($1)
131
- @bank_statement.transactions << @transaction
132
- @tag86 = false
133
- end
134
- end
135
-
136
- def parse_tag_86
137
- if !@tag86 && @line.match(/^:86:\s?(.*)\Z/m)
138
- @tag86 = true
139
- @transaction.description = $1.gsub(/\n/, ' ').gsub(/>\d{2}/, '').strip
140
- parse_contra_account
141
- end
142
- end
143
-
144
- def parse_line
145
- if @tag86 && @transaction.description
146
- @transaction.description.lstrip!
147
- @transaction.description += ' ' + @line.gsub(/\n/, ' ').gsub(/>\d{2}\s*/, '').gsub(/\-XXX/, '').gsub(/-$/, '').strip
148
- @transaction.description.strip!
149
- end
150
- end
151
-
152
- def parse_date(string)
153
- Date.new(2000 + string[0..1].to_i, string[2..3].to_i, string[4..5].to_i) if string
154
- end
155
-
156
- def parse_contra_account
157
- end
158
-
159
- #Fail silently
160
- def method_missing(*args)
161
- end
162
-
163
- end
164
-
165
- end
@@ -1,16 +0,0 @@
1
- module MT940::StructuredFormat
2
- def parse_line
3
- super unless @skip_parse_line
4
- end
5
-
6
- def read_all_description_lines!
7
- @skip_parse_line = true
8
- index = @lines.index(@line)
9
- @lines[index+1..-1].each do |line|
10
- break if line.match MT940::Base::MT_940_TAG_LINE
11
- @transaction.description.lstrip!
12
- @transaction.description += line.gsub(/\n/, '').gsub(/>\d{2}\s*/, '').gsub(/\-XXX/, '').gsub(/-$/, '').strip
13
- @transaction.description.strip!
14
- end
15
- end
16
- end
@@ -1,48 +0,0 @@
1
- require_relative 'spec_helper'
2
-
3
- describe "Base" do
4
-
5
- context 'MT940::Base' do
6
- it 'read the transactions with the filename of the MT940 file' do
7
- file_name = File.dirname(__FILE__) + '/fixtures/ing.txt'
8
- @transactions = MT940::Base.parse_mt940(file_name)["1234567"].flat_map(&:transactions)
9
- @transactions.size.should == 6
10
- end
11
-
12
- it 'read the transactions with the handle to the mt940 file itself' do
13
- file_name = File.dirname(__FILE__) + '/fixtures/ing.txt'
14
- file = File.open(file_name)
15
- @transactions = MT940::Base.parse_mt940(file)["1234567"].flat_map(&:transactions)
16
- @transactions.size.should == 6
17
- end
18
-
19
- #Tempfile is used by Paperclip, so the following will work:
20
- #MT940::Base.transactions(@mt940_file.attachment.to_file)
21
- it 'read the transactions with the handle of a Tempfile' do
22
- file = Tempfile.new('temp')
23
- file.write(':940:')
24
- file.rewind
25
- @transactions = MT940::Base.parse_mt940(file)
26
- @transactions.size.should == 0
27
- file.unlink
28
- end
29
-
30
- it 'raise an exception if the file does not exist' do
31
- file_name = File.dirname(__FILE__) + '/fixtures/123.txt'
32
- expect {MT940::Base.parse_mt940(file_name)}.to raise_exception Errno::ENOENT
33
- end
34
-
35
- it 'raise an ArgumentError if a wrong argument was given' do
36
- expect {MT940::Base.parse_mt940(Hash.new)}.to raise_exception ArgumentError
37
- end
38
- end
39
-
40
- context 'Unknown MT940 file' do
41
- it 'return its bank' do
42
- file_name = File.dirname(__FILE__) + '/fixtures/unknown.txt'
43
- @transactions = MT940::Base.parse_mt940(file_name)["1234567"].flat_map(&:transactions)
44
- @transactions.first.bank.should == 'Unknown'
45
- end
46
- end
47
-
48
- end