mt940_parser 1.0.5 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 39104db11a7d233e6d20eb364248aafa38043c40
4
- data.tar.gz: 68fb60ee4af59dd5490736b0fe9906c5ea7d96fe
3
+ metadata.gz: 90c03b829e6f715e6255c89672b49fb07564e6de
4
+ data.tar.gz: 838b67c8f1e8552b2118fe2e224fb24c6f26341e
5
5
  SHA512:
6
- metadata.gz: 6851743254ef137afd2ec83744c73acf7a10f1cd990259ab12f0018f6e870274933d91820ef058ccfde578939d6547249b00186205affc6c32552b4421c34f20
7
- data.tar.gz: 95e73d8a4c876d3484f489edc5985ddceb809c7b2c3ba44ff525e869bf9596c0171ca7a53f739f720e705594d3fc1b7b2f6294eb2f1270b72a70cd3445f8f5ed
6
+ metadata.gz: d062a25b89d4d24d9eaaea209630c4b2cec15b6929e5c17ea35401875c0d87fe89d227b1073c8a82af03402af42a90f4ca60007c00ee7456d7049ab3295a50e2
7
+ data.tar.gz: ff659e396c6f01a5978b27e513b2254bd6e93cf40d10c2bc9fd08bf82a9b00643dacbcddc11f3780eb83349bed90b682af8c971162fd4ac781afd7ad41dc771d
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0-p594
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ rvm:
2
+ - 2.0.0
3
+ - 2.1
4
+ - ruby-head
5
+ - jruby-head
6
+ matrix:
7
+ allow_failures:
8
+ - rvm: ruby-head
9
+ - rvm: jruby-head
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
- ---
1
+ ---
2
2
  :major: 1
3
- :minor: 0
4
- :build:
5
- :patch: 5
3
+ :minor: 2
4
+ :patch: 0
5
+ :build:
@@ -1,5 +1,5 @@
1
1
  # this is a beautification wrapper around the low-level
2
- # MT940.parse command. use it in order to make dealing with
2
+ # MT940.parse command. use it in order to make dealing with
3
3
  # the data easier
4
4
  class MT940
5
5
 
@@ -10,20 +10,19 @@ class MT940
10
10
  def self.parse_file(file)
11
11
  self.parse(File.read(file))
12
12
  end
13
-
13
+
14
14
  def self.parse(data)
15
15
  messages = MT940.parse(data)
16
16
  messages.map { |msg| new(msg) }
17
17
  end
18
-
19
- def initialize(raw_mt940)
20
- @raw = raw_mt940
21
- @account = @raw.find { |line| line.class == MT940::Account }
18
+
19
+ def initialize(lines)
20
+ @account = lines.find { |line| line.class == MT940::Account }
22
21
  @statement_lines = []
23
- @raw.each_with_index do |line, i|
22
+ lines.each_with_index do |line, i|
24
23
  next unless line.class == MT940::StatementLine
25
- ensure_is_info_line!(@raw[i+1])
26
- @statement_lines << StatementLineBundle.new(@raw[i], @raw[i+1])
24
+ ensure_is_info_line!(lines[i+1])
25
+ @statement_lines << StatementLineBundle.new(lines[i], lines[i+1])
27
26
  end
28
27
  end
29
28
 
@@ -35,16 +34,16 @@ class MT940
35
34
  @account.account_number
36
35
  end
37
36
 
38
- private
39
-
37
+ private
38
+
40
39
  def ensure_is_info_line!(line)
41
40
  unless line.is_a?(MT940::StatementLineInformation)
42
- raise StandardError, "Unexpected Structure; expected StatementLineInformation, but was #{line.class}"
41
+ raise StandardError, "Unexpected Structure; expected StatementLineInformation, but was #{line.class}"
43
42
  end
44
43
  end
45
-
44
+
46
45
  end
47
-
46
+
48
47
  class StatementLineBundle
49
48
 
50
49
  METHOD_MAP = {
@@ -71,5 +70,5 @@ class MT940
71
70
  end
72
71
 
73
72
  end
74
-
75
- end
73
+
74
+ end
data/lib/mt940.rb CHANGED
@@ -3,10 +3,10 @@ require 'mt940/customer_statement_message'
3
3
  class MT940
4
4
  class Field
5
5
  attr_reader :modifier, :content
6
-
6
+
7
7
  DATE = /(\d{2})(\d{2})(\d{2})/
8
8
  SHORT_DATE = /(\d{2})(\d{2})/
9
-
9
+
10
10
  class << self
11
11
 
12
12
  def for(line)
@@ -24,16 +24,16 @@ class MT940
24
24
  '65' => FutureValutaBalance,
25
25
  '86' => StatementLineInformation
26
26
  }[number]
27
-
27
+
28
28
  raise StandardError, "Field #{number} is not implemented" unless klass
29
-
29
+
30
30
  klass.new(modifier, content)
31
31
  else
32
32
  raise StandardError, "Wrong line format: #{line.dump}"
33
33
  end
34
34
  end
35
35
  end
36
-
36
+
37
37
  def initialize(modifier, content)
38
38
  @modifier = modifier
39
39
  parse_content(content)
@@ -42,14 +42,14 @@ class MT940
42
42
  private
43
43
  def parse_amount_in_cents(amount)
44
44
  # don't use Integer(amount) function, because amount can be "008" - interpreted as octal number ("010" = 8)
45
- amount.gsub(',', '').to_i
45
+ amount.gsub(',', '').to_i
46
46
  end
47
-
47
+
48
48
  def parse_date(date)
49
49
  date.match(DATE)
50
50
  Date.new("20#{$1}".to_i, $2.to_i, $3.to_i)
51
51
  end
52
-
52
+
53
53
  def parse_entry_date(raw_entry_date, value_date)
54
54
  raw_entry_date.match(SHORT_DATE)
55
55
  entry_date = Date.new(value_date.year, $1.to_i, $2.to_i)
@@ -63,16 +63,16 @@ class MT940
63
63
  # 20
64
64
  class Job < Field
65
65
  attr_reader :reference
66
-
66
+
67
67
  def parse_content(content)
68
68
  @reference = content
69
69
  end
70
70
  end
71
-
71
+
72
72
  # 21
73
73
  class Reference < Job
74
74
  end
75
-
75
+
76
76
  # 25
77
77
  class Account < Field
78
78
  attr_reader :bank_code, :account_number, :account_currency
@@ -84,13 +84,13 @@ class MT940
84
84
  @bank_code, @account_number, @account_currency = $1, $2, $3
85
85
  end
86
86
  end
87
-
87
+
88
88
  # 28
89
89
  class Statement < Field
90
90
  attr_reader :number, :sheet
91
91
 
92
92
  CONTENT = /^(0|(\d{5,5})\/(\d{2,5}))$/
93
-
93
+
94
94
  def parse_content(content)
95
95
  content.match(CONTENT)
96
96
  if $1 == '0'
@@ -100,13 +100,13 @@ class MT940
100
100
  end
101
101
  end
102
102
  end
103
-
103
+
104
104
  # 60
105
105
  class AccountBalance < Field
106
106
  attr_reader :balance_type, :sign, :currency, :amount, :date
107
107
 
108
108
  CONTENT = /^(C|D)(\w{6})(\w{3})(\d{1,12},\d{0,2})$/
109
-
109
+
110
110
  def parse_content(content)
111
111
  content.match(CONTENT)
112
112
 
@@ -116,27 +116,27 @@ class MT940
116
116
  when 'M'
117
117
  :intermediate
118
118
  end
119
-
119
+
120
120
  @sign = case $1
121
121
  when 'C'
122
122
  :credit
123
123
  when 'D'
124
124
  :debit
125
125
  end
126
-
126
+
127
127
  raw_date = $2
128
128
  @currency = $3
129
129
  @amount = parse_amount_in_cents($4)
130
-
130
+
131
131
  @date = case raw_date
132
132
  when 'ALT', '0'
133
133
  nil
134
134
  when DATE
135
- Date.new("20#{$1}".to_i, $2.to_i, $3.to_i)
135
+ Date.new("20#{$1}".to_i, $2.to_i, $3.to_i)
136
136
  end
137
137
  end
138
138
  end
139
-
139
+
140
140
  # 61
141
141
  class StatementLine < Field
142
142
  attr_reader :date, :entry_date, :funds_code, :amount, :swift_code, :reference, :transaction_description
@@ -145,7 +145,7 @@ class MT940
145
145
 
146
146
  def parse_content(content)
147
147
  content.match(CONTENT)
148
-
148
+
149
149
  raw_date = $1
150
150
  raw_entry_date = $2
151
151
  @funds_code = case $3
@@ -158,25 +158,25 @@ class MT940
158
158
  when 'RD'
159
159
  :return_debit
160
160
  end
161
-
161
+
162
162
  @amount = parse_amount_in_cents($4)
163
163
  @swift_code = $5
164
164
  @reference = $6
165
165
  @transaction_description = $7
166
-
166
+
167
167
  @date = parse_date(raw_date)
168
168
  @entry_date = parse_entry_date(raw_entry_date, @date) if raw_entry_date
169
169
  end
170
-
170
+
171
171
  def value_date
172
172
  @date
173
173
  end
174
174
  end
175
-
175
+
176
176
  # 62
177
177
  class ClosingBalance < AccountBalance
178
178
  end
179
-
179
+
180
180
  # 64
181
181
  class ValutaBalance < AccountBalance
182
182
  end
@@ -184,23 +184,23 @@ class MT940
184
184
  # 65
185
185
  class FutureValutaBalance < AccountBalance
186
186
  end
187
-
187
+
188
188
  # 86
189
189
  class StatementLineInformation < Field
190
- attr_reader :code, :transaction_description, :prima_nota, :details, :bank_code, :account_number,
190
+ attr_reader :code, :transaction_description, :prima_nota, :details, :bank_code, :account_number,
191
191
  :account_holder, :text_key_extension, :not_implemented_fields
192
-
192
+
193
193
  def parse_content(content)
194
194
  content.match(/^(\d{3})((.).*)$/)
195
195
  @code = $1.to_i
196
-
196
+
197
197
  details = []
198
198
  account_holder = []
199
199
 
200
200
  if seperator = $3
201
201
  sub_fields = $2.scan(/#{Regexp.escape(seperator)}(\d{2})([^#{Regexp.escape(seperator)}]*)/)
202
-
203
-
202
+
203
+
204
204
  sub_fields.each do |(code, content)|
205
205
  case code.to_i
206
206
  when 0
@@ -225,19 +225,19 @@ class MT940
225
225
  end
226
226
  end
227
227
  end
228
-
228
+
229
229
  @details = details.join("\n")
230
230
  @account_holder = account_holder.join("\n")
231
231
  end
232
232
  end
233
-
233
+
234
234
 
235
235
  class << self
236
236
  def parse(text)
237
237
  raise "Invalid encoding!" unless text.valid_encoding?
238
238
  new_text = text.encode('utf-8').strip
239
239
  new_text << "\r\n" if new_text[-1,1] == '-'
240
- raw_sheets = new_text.split(/^-\r\n/).map { |sheet| sheet.gsub(/\r\n(?!:)/, '') }
240
+ raw_sheets = new_text.split(/^-\s*\r\n/).map { |sheet| sheet.gsub(/\r\n(?!:)/, '') }
241
241
  sheets = raw_sheets.map { |raw_sheet| parse_sheet(raw_sheet) }
242
242
  end
243
243
 
data/mt940_parser.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "mt940_parser"
8
- s.version = "1.0.5"
8
+ s.version = "1.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Thies C. Arntzen", "Phillip Oertel"]
12
- s.date = "2014-02-04"
12
+ s.date = "2015-01-07"
13
13
  s.email = "developers@betterplace.org"
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE",
@@ -17,7 +17,9 @@ Gem::Specification.new do |s|
17
17
  ]
18
18
  s.files = [
19
19
  ".document",
20
+ ".ruby-version",
20
21
  ".specification",
22
+ ".travis.yml",
21
23
  "Gemfile",
22
24
  "Gemfile.lock",
23
25
  "LICENSE",
@@ -58,11 +60,11 @@ Gem::Specification.new do |s|
58
60
  s.homepage = "http://github.com/betterplace/mt940_parser"
59
61
  s.licenses = ["MIT"]
60
62
  s.require_paths = ["lib"]
61
- s.rubygems_version = "1.8.24"
63
+ s.rubygems_version = "2.0.14"
62
64
  s.summary = "MT940 parses account statements in the SWIFT MT940 format."
63
65
 
64
66
  if s.respond_to? :specification_version then
65
- s.specification_version = 3
67
+ s.specification_version = 4
66
68
 
67
69
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
68
70
  s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
data/test/test_mt940.rb CHANGED
@@ -6,18 +6,9 @@ YAML::ENGINE.yamler = 'psych'
6
6
  # $DEBUG = true
7
7
  class TestMt940 < Test::Unit::TestCase
8
8
 
9
- def read_mt940_data(file)
10
- MT940.parse(IO.read(file))
11
- end
12
-
13
- def writeout(name, data)
14
-
15
- File.open(name, "w") { |f| f.write data }
16
- end
17
-
18
9
  def test_it_should_parse_fixture_files_correctly
19
10
  Dir[File.dirname(__FILE__) + "/fixtures/*.txt"].reject { |f| f =~ /sepa_snippet/ }.each do |file|
20
- data = read_mt940_data(file)
11
+ data = MT940.parse(IO.read(file))
21
12
  generated_structure_file = file.gsub(/.txt$/, ".yml")
22
13
 
23
14
  assert_equal YAML::load_file(generated_structure_file).to_yaml, data.to_yaml
@@ -33,4 +24,4 @@ class TestMt940 < Test::Unit::TestCase
33
24
  end
34
25
  end
35
26
 
36
- end
27
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mt940_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thies C. Arntzen
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-05 00:00:00.000000000 Z
12
+ date: 2015-01-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -62,7 +62,9 @@ extra_rdoc_files:
62
62
  - README.rdoc
63
63
  files:
64
64
  - .document
65
+ - .ruby-version
65
66
  - .specification
67
+ - .travis.yml
66
68
  - Gemfile
67
69
  - Gemfile.lock
68
70
  - LICENSE
@@ -119,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
121
  version: '0'
120
122
  requirements: []
121
123
  rubyforge_project:
122
- rubygems_version: 2.2.1
124
+ rubygems_version: 2.0.14
123
125
  signing_key:
124
126
  specification_version: 4
125
127
  summary: MT940 parses account statements in the SWIFT MT940 format.