cmxl 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,4 +3,7 @@ rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
5
  - 2.1.2
6
- - jruby
6
+ - jruby
7
+ addons:
8
+ code_climate:
9
+ repo_token: 149f0d20e17ace00c44be432a4194bc441ba805da89a7708fca0f4a2c3f2aed7
@@ -0,0 +1,3 @@
1
+ # 0.1.2
2
+
3
+ * [BUGFIX] fixed the statement details parser. It failed in case of empty values in the details
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem "codeclimate-test-reporter", group: :test, require: nil
3
4
  # Specify your gem's dependencies in cmxl.gemspec
4
5
  gemspec
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Cmxl - your friendly ruby MT940 parser
2
2
 
3
- At Railslove we build a lot of banking and payment applications and work on integrating applications with banks and banking functionality.
4
- Our goal is to making it easy with what sometimes seems complicated.
3
+ At [Railslove](http://railslove.com) we build a lot of financial applications and work on integrating applications with banks and banking functionality.
4
+ Our goal is to make simple solutions for what often looks complicated.
5
5
 
6
6
  Cmxl is a friendly and extendible MT940 bank statement file parser that helps your extracting data from the bank statement files.
7
7
 
@@ -15,9 +15,9 @@ At some point in the future MT940 file should be exchanged with newer XML docume
15
15
 
16
16
  ## Reqirements
17
17
 
18
- Cmxl is a pure ruby parser and has no gem dependencies.
18
+ Cmxl is a pure ruby parser and has no dependency on native extensions.
19
19
 
20
- * Ruby 1.9.3 or newer
20
+ * Ruby 1.9.3 or newer (jruby, etc.)
21
21
 
22
22
  ## Installation
23
23
 
@@ -48,13 +48,13 @@ Cmxl.config[:raise_line_format_errors] = true
48
48
 
49
49
  # Statment parsing:
50
50
 
51
- statements = Cmxl.parse(File.read('mt940.txt'), :encoding => 'ISO-8859-1') # parses the file and returns an array of statement objects
51
+ statements = Cmxl.parse(File.read('mt940.txt'), :encoding => 'ISO-8859-1') # parses the file and returns an array of statement objects. Please note: if no encoding is given Cmxl tries to guess the encoding from the content and converts it to UTF-8.
52
52
  statements.each do |s|
53
53
  puts s.reference
54
54
  puts s.generation_date
55
55
  puts s.opening_balance.amount
56
56
  puts s.closing_balance.amount
57
- puts.sha # SHA of the statement source - could be used as an unique identifier
57
+ puts s.sha # SHA of the statement source - could be used as an unique identifier
58
58
 
59
59
  s.transactions.each do |t|
60
60
  puts t.information
@@ -76,18 +76,18 @@ end
76
76
 
77
77
  ```
78
78
 
79
- Every object responds to `to_h` and let's you easily convert the data to a hash.
79
+ Every object responds to `to_h` and let's you easily convert the data to a hash. Also every object responds to `to_json` which lets you easily represent the statements as JSON with your favorit JSON library.
80
80
 
81
81
  #### A note about encoding and file wirednesses
82
82
 
83
83
  You probably will encounter encoding issues (hey, you are building banking applications!).
84
- We try to handle encoding and format wirednesses as much as possible.
85
- If you have encoding issues you can pass encoding options to the `Cmxl.parse(<string>, <options hash>)` it accepts the same options as [String#encode](http://ruby-doc.org/core-2.1.3/String.html#method-i-encode)
84
+ We try to handle encoding and format wirednesses as much as possible. If no encoding is passed we try to guess the encoding of the data and convert it to UTF8.
85
+ In the likely case that you encouter encoding issues you can pass encoding options to the `Cmxl.parse(<string>, <options hash>)` it accepts the same options as [String#encode](http://ruby-doc.org/core-2.1.3/String.html#method-i-encode)
86
86
  If that fails try to motify the file before you pass it to the parser - and please create an issue.
87
87
 
88
88
  ### Custom field parsers
89
89
 
90
- Because a lot of banks implement the MT940 format slightly different one of the design goals of this library is to be able to customize the field parsers.
90
+ Because a lot of banks implement the MT940 format slightly different one of the design goals of this library is to be able to customize the individual field parsers.
91
91
  Every line get parsed with a special parser. Here is how to write your own parser:
92
92
 
93
93
  ```ruby
@@ -120,10 +120,16 @@ If you have a file that can not be parsed please open an issue. We hope to build
120
120
  * collect MT940 files from different banks and use them as example for specs
121
121
 
122
122
 
123
+ ## Looking for other Banking and EBICS tools?
124
+
125
+ Maybe these are also interesting for you.
126
+
127
+ * [EPICS: Open Source SEPA EBICS client](https://railslove.github.io/epics/) full implementation to manage all the banking activities like direct debits, credits, etc. (SEPA Lastschrift, Überweisungen, etc.)
128
+ * [EBICS::Box: out of the box solution to automate banking activities](http://www.railslove.com/ebics-box) - The missing API for your bank
129
+
123
130
  ## Contributing
124
131
 
125
- ### Specs
126
- We use rspec to test Cmxl. Run `rake` to execute the whole test suite.
132
+ Automated tests: We use rspec to test Cmxl. Simply run `rake` to execute the whole test suite.
127
133
 
128
134
  1. Fork it ( http://github.com/railslove/cmxl/fork )
129
135
  2. Create your feature branch (`git checkout -b my-new-feature`)
@@ -139,10 +145,14 @@ other parsers:
139
145
  * [betterplace/mt940_parser](https://github.com/betterplace/mt940_parser)
140
146
  * [gmitrev/mt940parser](https://github.com/gmitrev/mt940parser)
141
147
 
148
+
142
149
  ## Stats
143
150
 
144
- [![Build Status](https://magnum.travis-ci.com/railslove/cmxl.svg?token=e6QUckhTMdWWujkwZNBD&branch=master)](https://magnum.travis-ci.com/railslove/cmxl)
151
+ [![Build Status](https://travis-ci.org/railslove/cmxl.svg)](https://travis-ci.org/railslove/cmxl)
152
+ [![Code Climate](https://codeclimate.com/github/railslove/cmxl/badges/gpa.svg)](https://codeclimate.com/github/railslove/cmxl)
153
+ [![Test Coverage](https://codeclimate.com/github/railslove/cmxl/badges/coverage.svg)](https://codeclimate.com/github/railslove/cmxl)
154
+ [![Gem Version](https://badge.fury.io/rb/cmxl.svg)](http://badge.fury.io/rb/cmxl)
145
155
 
146
156
  ------------
147
157
 
148
- 2014 - built with love by [Railslove](http://railslove.com). We have built quite a number of FinTech products. If you need support we are happy to help. Please contact us at team@railslove.com.
158
+ 2014 - built with love by [Railslove](http://railslove.com) and released under the MIT-Licence. We have built quite a number of FinTech products. If you need support we are happy to help. Please contact us at team@railslove.com.
@@ -6,7 +6,7 @@ module Cmxl
6
6
 
7
7
  def sub_fields
8
8
  @sub_fields ||= if self.data['details'] =~ /#{Regexp.escape(self.data['seperator'])}(\d{2})/
9
- Hash[*self.data['details'].split(/#{Regexp.escape(self.data['seperator'])}(\d{2})/).reject(&:empty?)]
9
+ Hash[self.data['details'].scan(/#{Regexp.escape(self.data['seperator'])}(\d{2})([^#{Regexp.escape(self.data['seperator'])}]*)/)]
10
10
  else
11
11
  {}
12
12
  end
@@ -34,7 +34,7 @@ module Cmxl
34
34
  end
35
35
 
36
36
  def name
37
- "#{self.sub_fields['32']}#{self.sub_fields['33']}"
37
+ [self.sub_fields['32'], self.sub_fields['33']].compact.join(" ")
38
38
  end
39
39
 
40
40
  def iban
@@ -44,7 +44,7 @@ module Cmxl
44
44
  # Public: SHA2 of the provided source
45
45
  # This is an experiment of trying to identify statements. The MT940 itself might not provide a unique identifier
46
46
  #
47
- # Retruns the SHA2 of the source
47
+ # Returns the SHA2 of the source
48
48
  def sha
49
49
  Digest::SHA2.new.update(self.source).to_s
50
50
  end
@@ -1,3 +1,3 @@
1
1
  module Cmxl
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -25,6 +25,7 @@ describe Cmxl::Fields::StatementDetails do
25
25
  "30" => "HYVEDEMMXXX",
26
26
  "31" => "HUkkbbbsssskcccccccccccccccx",
27
27
  "32" => "Peter Pan",
28
+ "99" => "",
28
29
  "34" => "171"
29
30
  }) }
30
31
  it { expect(subject.sepa).to eql({
@@ -34,7 +35,7 @@ describe Cmxl::Fields::StatementDetails do
34
35
  "SVWZ" => "FOO TRX-0A4A47C3-F846-4729-8A1B-5DF620F"
35
36
  }) }
36
37
 
37
- it { expect(subject.to_h).to eql({'bic'=>"HYVEDEMMXXX", 'iban'=>"HUkkbbbsssskcccccccccccccccx", 'name' => "Peter Pan", 'sepa' => {"EREF"=>"TRX-0A4A47C3-F846-4729-8A1B-5DF620F", "MREF"=>"CAC97D2144174318AC18D9BF815BD4FB", "CRED"=>"DE98ZZZ09999999999", "SVWZ"=>"FOO TRX-0A4A47C3-F846-4729-8A1B-5DF620F"}, 'information' => "EREF+TRX-0A4A47C3-F846-4729-8A1B-5DF620FMREF+CAC97D2144174318AC18D9BF815BD4FBCRED+DE98ZZZ09999999999SVWZ+FOO TRX-0A4A47C3-F846-4729-8A1B-5DF620F", 'description' => "SEPA LASTSCHRIFT KUNDE", 'sub_fields' => {"00"=>"SEPA LASTSCHRIFT KUNDE", "10"=>"281", "20"=>"EREF+TRX-0A4A47C3-F846-4729", "21"=>"-8A1B-5DF620F", "22"=>"MREF+CAC97D2144174318AC18D9", "23"=>"BF815BD4FB", "24"=>"CRED+DE98ZZZ09999999999", "25"=>"SVWZ+FOO TRX-0A4A47C3-F84", "26"=>"6-4729-8A1B-5DF620F", "30"=>"HYVEDEMMXXX", "31"=>"HUkkbbbsssskcccccccccccccccx", "32"=>"Peter Pan", "34"=>"171"}, 'transaction_code' => "171", 'details' => "?00SEPA LASTSCHRIFT KUNDE?10281?20EREF+TRX-0A4A47C3-F846-4729?21-8A1B-5DF620F?22MREF+CAC97D2144174318AC18D9?23BF815BD4FB?24CRED+DE98ZZZ09999999999?25SVWZ+FOO TRX-0A4A47C3-F84?266-4729-8A1B-5DF620F?30HYVEDEMMXXX?31HUkkbbbsssskcccccccccccccccx?32Peter Pan?34171"}) }
38
+ it { expect(subject.to_h).to eql({'bic'=>"HYVEDEMMXXX", 'iban'=>"HUkkbbbsssskcccccccccccccccx", 'name' => "Peter Pan", 'sepa' => {"EREF"=>"TRX-0A4A47C3-F846-4729-8A1B-5DF620F", "MREF"=>"CAC97D2144174318AC18D9BF815BD4FB", "CRED"=>"DE98ZZZ09999999999", "SVWZ"=>"FOO TRX-0A4A47C3-F846-4729-8A1B-5DF620F"}, 'information' => "EREF+TRX-0A4A47C3-F846-4729-8A1B-5DF620FMREF+CAC97D2144174318AC18D9BF815BD4FBCRED+DE98ZZZ09999999999SVWZ+FOO TRX-0A4A47C3-F846-4729-8A1B-5DF620F", 'description' => "SEPA LASTSCHRIFT KUNDE", 'sub_fields' => {"00"=>"SEPA LASTSCHRIFT KUNDE", "10"=>"281", "20"=>"EREF+TRX-0A4A47C3-F846-4729", "21"=>"-8A1B-5DF620F", "22"=>"MREF+CAC97D2144174318AC18D9", "23"=>"BF815BD4FB", "24"=>"CRED+DE98ZZZ09999999999", "25"=>"SVWZ+FOO TRX-0A4A47C3-F84", "26"=>"6-4729-8A1B-5DF620F", "30"=>"HYVEDEMMXXX", "31"=>"HUkkbbbsssskcccccccccccccccx", "32"=>"Peter Pan", "34"=>"171", "99" => ""}, 'transaction_code' => "171", 'details' => "?00SEPA LASTSCHRIFT KUNDE?10281?20EREF+TRX-0A4A47C3-F846-4729?21-8A1B-5DF620F?22MREF+CAC97D2144174318AC18D9?23BF815BD4FB?24CRED+DE98ZZZ09999999999?25SVWZ+FOO TRX-0A4A47C3-F84?266-4729-8A1B-5DF620F?30HYVEDEMMXXX?31HUkkbbbsssskcccccccccccccccx?32Peter Pan?99?34171"}) }
38
39
  it { expect(subject.to_hash).to eql(subject.to_h) }
39
40
  end
40
41
 
@@ -1 +1 @@
1
- :86:171?00SEPA LASTSCHRIFT KUNDE?10281?20EREF+TRX-0A4A47C3-F846-4729?21-8A1B-5DF620F?22MREF+CAC97D2144174318AC18D9?23BF815BD4FB?24CRED+DE98ZZZ09999999999?25SVWZ+FOO TRX-0A4A47C3-F84?266-4729-8A1B-5DF620F?30HYVEDEMMXXX?31HUkkbbbsssskcccccccccccccccx?32Peter Pan?34171
1
+ :86:171?00SEPA LASTSCHRIFT KUNDE?10281?20EREF+TRX-0A4A47C3-F846-4729?21-8A1B-5DF620F?22MREF+CAC97D2144174318AC18D9?23BF815BD4FB?24CRED+DE98ZZZ09999999999?25SVWZ+FOO TRX-0A4A47C3-F84?266-4729-8A1B-5DF620F?30HYVEDEMMXXX?31HUkkbbbsssskcccccccccccccccx?32Peter Pan?99?34171
@@ -55,7 +55,7 @@ describe 'parsing a statement' do
55
55
  it { expect(subject.transactions.count).to eql(3) }
56
56
  it { expect(subject.transactions.first.description).to eql('Wyplata-(dysp/przel)') }
57
57
  it { expect(subject.transactions.first.information).to eql('0810600076000077777777777715617INFO INFO INFO INFO INFO INFO 1 ENDINFO INFO INFO INFO INFOINFO 2 ENDZAPLATA ZA FABRYKATY DO TUB - 200 S ZTUK, TRANZYSTORY-300 SZT GR544 I OPORNIKI-500 SZT GTX847 FAKTURA 333/2003.') }
58
- it { expect(subject.transactions.first.name).to eql('HUTA SZKLA TOPIC ULPRZEMYSLOWA 67 32-669 WROCLAW') }
58
+ it { expect(subject.transactions.first.name).to eql('HUTA SZKLA TOPIC ULPRZEMY SLOWA 67 32-669 WROCLAW') }
59
59
  it { expect(subject.transactions.first.bic).to eql('10600076') }
60
60
  it { expect(subject.transactions.first.iban).to eql('PL08106000760000777777777777') }
61
61
  it { expect(subject.transactions.first.sepa).to eql({}) }
@@ -1,8 +1,12 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
 
4
+ require "codeclimate-test-reporter"
5
+ CodeClimate::TestReporter.start
6
+
4
7
  require 'cmxl'
5
8
 
9
+
6
10
  puts File.join(File.dirname(__FILE__), "support/**/*.rb").to_s
7
11
  Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each {|f| require f}
8
12
 
@@ -12,7 +12,7 @@ describe Cmxl::Transaction do
12
12
  it { expect(subject.amount).to eql(1.62)}
13
13
  it { expect(subject.statement_line.amount).to eql(1.62)}
14
14
  it { expect(subject.amount_in_cents).to eql(162)}
15
- it { expect(subject.to_h).to eql({"date"=>Date.new(2014,9,1), "sha" => "3c5e65aa3d3878b06b58b6f1ae2f3693004dfb04e3ab7119a1c1244e612293da", "entry_date"=>Date.new(2014,9,2), "funds_code"=>"D", "currency_letter"=>"R", "amount"=>1.62, "swift_code"=>"NTRF", "reference"=>"0000549855700010", "bank_reference"=>"025498557/000001", "amount_in_cents"=>162, "sign"=>-1, "debit"=>true, "credit"=>false, "bic"=>"HYVEDEMMXXX", "iban"=>"HUkkbbbsssskcccccccccccccccx", "name"=>"Peter Pan", "sepa"=>{"EREF"=>"TRX-0A4A47C3-F846-4729-8A1B-5DF620F", "MREF"=>"CAC97D2144174318AC18D9BF815BD4FB", "CRED"=>"DE98ZZZ09999999999", "SVWZ"=>"FOO TRX-0A4A47C3-F846-4729-8A1B-5DF620F"}, "information"=>"EREF+TRX-0A4A47C3-F846-4729-8A1B-5DF620FMREF+CAC97D2144174318AC18D9BF815BD4FBCRED+DE98ZZZ09999999999SVWZ+FOO TRX-0A4A47C3-F846-4729-8A1B-5DF620F", "description"=>"SEPA LASTSCHRIFT KUNDE", "sub_fields"=>{"00"=>"SEPA LASTSCHRIFT KUNDE", "10"=>"281", "20"=>"EREF+TRX-0A4A47C3-F846-4729", "21"=>"-8A1B-5DF620F", "22"=>"MREF+CAC97D2144174318AC18D9", "23"=>"BF815BD4FB", "24"=>"CRED+DE98ZZZ09999999999", "25"=>"SVWZ+FOO TRX-0A4A47C3-F84", "26"=>"6-4729-8A1B-5DF620F", "30"=>"HYVEDEMMXXX", "31"=>"HUkkbbbsssskcccccccccccccccx", "32"=>"Peter Pan", "34"=>"171"}, "transaction_code"=>"171", "details"=>"?00SEPA LASTSCHRIFT KUNDE?10281?20EREF+TRX-0A4A47C3-F846-4729?21-8A1B-5DF620F?22MREF+CAC97D2144174318AC18D9?23BF815BD4FB?24CRED+DE98ZZZ09999999999?25SVWZ+FOO TRX-0A4A47C3-F84?266-4729-8A1B-5DF620F?30HYVEDEMMXXX?31HUkkbbbsssskcccccccccccccccx?32Peter Pan?34171"}) }
15
+ it { expect(subject.to_h).to eql({"date"=>Date.new(2014,9,1), "sha" => "3c5e65aa3d3878b06b58b6f1ae2f3693004dfb04e3ab7119a1c1244e612293da", "entry_date"=>Date.new(2014,9,2), "funds_code"=>"D", "currency_letter"=>"R", "amount"=>1.62, "swift_code"=>"NTRF", "reference"=>"0000549855700010", "bank_reference"=>"025498557/000001", "amount_in_cents"=>162, "sign"=>-1, "debit"=>true, "credit"=>false, "bic"=>"HYVEDEMMXXX", "iban"=>"HUkkbbbsssskcccccccccccccccx", "name"=>"Peter Pan", "sepa"=>{"EREF"=>"TRX-0A4A47C3-F846-4729-8A1B-5DF620F", "MREF"=>"CAC97D2144174318AC18D9BF815BD4FB", "CRED"=>"DE98ZZZ09999999999", "SVWZ"=>"FOO TRX-0A4A47C3-F846-4729-8A1B-5DF620F"}, "information"=>"EREF+TRX-0A4A47C3-F846-4729-8A1B-5DF620FMREF+CAC97D2144174318AC18D9BF815BD4FBCRED+DE98ZZZ09999999999SVWZ+FOO TRX-0A4A47C3-F846-4729-8A1B-5DF620F", "description"=>"SEPA LASTSCHRIFT KUNDE", "sub_fields"=>{"00"=>"SEPA LASTSCHRIFT KUNDE", "10"=>"281", "20"=>"EREF+TRX-0A4A47C3-F846-4729", "21"=>"-8A1B-5DF620F", "22"=>"MREF+CAC97D2144174318AC18D9", "23"=>"BF815BD4FB", "24"=>"CRED+DE98ZZZ09999999999", "25"=>"SVWZ+FOO TRX-0A4A47C3-F84", "26"=>"6-4729-8A1B-5DF620F", "30"=>"HYVEDEMMXXX", "31"=>"HUkkbbbsssskcccccccccccccccx", "32"=>"Peter Pan", "99" => "", "34"=>"171"}, "transaction_code"=>"171", "details"=>"?00SEPA LASTSCHRIFT KUNDE?10281?20EREF+TRX-0A4A47C3-F846-4729?21-8A1B-5DF620F?22MREF+CAC97D2144174318AC18D9?23BF815BD4FB?24CRED+DE98ZZZ09999999999?25SVWZ+FOO TRX-0A4A47C3-F84?266-4729-8A1B-5DF620F?30HYVEDEMMXXX?31HUkkbbbsssskcccccccccccccccx?32Peter Pan?99?34171"}) }
16
16
  end
17
17
 
18
18
  context 'without details' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cmxl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-09-29 00:00:00.000000000 Z
12
+ date: 2015-10-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -85,6 +85,7 @@ extra_rdoc_files: []
85
85
  files:
86
86
  - .gitignore
87
87
  - .travis.yml
88
+ - CHANGELOG.mdown
88
89
  - Gemfile
89
90
  - LICENSE.txt
90
91
  - README.md