cmxl 1.4.1 → 1.5.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.
- checksums.yaml +4 -4
- data/.travis.yml +6 -15
- data/CHANGELOG.mdown +39 -11
- data/Gemfile +0 -1
- data/README.md +14 -18
- data/lib/cmxl.rb +2 -2
- data/lib/cmxl/fields/account_balance.rb +1 -1
- data/lib/cmxl/fields/statement_details.rb +5 -0
- data/lib/cmxl/fields/transaction.rb +5 -1
- data/lib/cmxl/statement.rb +3 -2
- data/lib/cmxl/version.rb +1 -1
- data/spec/fields/account_balance_spec.rb +7 -0
- data/spec/fields/statement_details_spec.rb +1 -0
- data/spec/fields/transaction_spec.rb +16 -0
- data/spec/fixtures/lines/account_balance_debit_broken.txt +1 -0
- data/spec/fixtures/lines/statement_line.txt +2 -0
- data/spec/fixtures/mt940.txt +31 -0
- data/spec/fixtures/mt942.txt +12 -0
- data/spec/fixtures/statement-details-mt940.txt +1 -1
- data/spec/mt940_parsing_spec.rb +8 -1
- data/spec/statement_spec.rb +23 -5
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 661a3296bdc88ce9874f07cb4a1cf4220bf1a60ea559e289edc5c5c34774764b
|
4
|
+
data.tar.gz: 4f0217f656646bd14540e5993f6419354641f30d901e8b7afc884b46fc5ac69e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 407ecb157601f8cc767ddb7699edbadc66582041cdcd8d1de3b3e169a41865d3f81ffdb794b7b9f8add8a55ecea1e16e4048f30a117cfe2401b05b487d2e1bcf
|
7
|
+
data.tar.gz: 4cbfe3e46cc9a00527bfa1a4d465f5e0ad4311d915449b45a81b172e1a653ee3ec2605778bb1241aca752016651b8f54dad0daf00769349a6a80cb679cff0dcf
|
data/.travis.yml
CHANGED
@@ -1,18 +1,9 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
-
- 2.
|
5
|
-
- 2.
|
6
|
-
- 2.
|
7
|
-
- 2.
|
8
|
-
- jruby-9.1.
|
9
|
-
|
10
|
-
then gem update --system 2.7.8;
|
11
|
-
else gem update --system;
|
12
|
-
fi
|
13
|
-
|
14
|
-
after_success:
|
15
|
-
- bundle exec codeclimate-test-reporter
|
16
|
-
addons:
|
17
|
-
code_climate:
|
18
|
-
repo_token: 149f0d20e17ace00c44be432a4194bc441ba805da89a7708fca0f4a2c3f2aed7
|
4
|
+
- 2.4.10
|
5
|
+
- 2.5.8
|
6
|
+
- 2.6.6
|
7
|
+
- 2.7.1
|
8
|
+
- jruby-9.1.17.0
|
9
|
+
- jruby-9.2.11.1
|
data/CHANGELOG.mdown
CHANGED
@@ -1,37 +1,65 @@
|
|
1
|
+
# NEXT release
|
2
|
+
|
3
|
+
# 1.5.0
|
4
|
+
|
5
|
+
- `[BUGFIX]` fix potential bug when generation_date is not provided in field 20 and 13 (issue: [#35](https://github.com/railslove/cmxl/issues/35) PR: [#36](https://github.com/railslove/cmxl/pull/36))
|
6
|
+
- `[FEATURE]` add transaction type 'S' to Field 61 (swift_code) (issue: [#38](https://github.com/railslove/cmxl/issues/38) PR: [#42](https://github.com/railslove/cmxl/pull/42)
|
7
|
+
- `[ENHANCEMENT]` [Fix deprecations in ruby 2.7 for kw params](https://github.com/railslove/cmxl/commit/905cd50e5372da312a653c89e77727a14751b5ec)
|
8
|
+
|
9
|
+
# 1.4.6
|
10
|
+
|
11
|
+
- `[ENHANCEMENT]` make sure that tag, gemversion and readme align ʘ‿ʘ
|
12
|
+
|
13
|
+
# 1.4.5
|
14
|
+
|
15
|
+
- `[ENHANCEMENT]` renames transaction_id to primanota
|
16
|
+
|
17
|
+
# 1.4.4
|
18
|
+
|
19
|
+
- `[FEATURE]` adds transaction id parsing to statement details
|
20
|
+
|
21
|
+
# 1.4.3
|
22
|
+
|
23
|
+
- `[BUGFIX]` parse field identifier only at the beginning of lines
|
24
|
+
|
25
|
+
# 1.4.2
|
26
|
+
|
27
|
+
- `[ENHANCEMENT]` handles broken account data without blowing up
|
28
|
+
|
1
29
|
# 1.4.1
|
2
30
|
|
3
|
-
- [BUGFIX] changes entry date calculation for transaction
|
31
|
+
- `[BUGFIX]` changes entry date calculation for transaction
|
4
32
|
Thanks to [@grncdr](https://github.com/grncdr)
|
5
33
|
|
6
34
|
# 1.4.0
|
7
35
|
|
8
|
-
- [FEATURE] adds ability to parse non-numerical tags ([#23](https://github.com/railslove/cmxl/issues/23)) \
|
36
|
+
- `[FEATURE]` adds ability to parse non-numerical tags ([#23](https://github.com/railslove/cmxl/issues/23)) \
|
9
37
|
Thanks to [@prometh07](https://github.com/prometh07)
|
10
38
|
|
11
39
|
# 1.3.0
|
12
40
|
|
13
|
-
- [FEATURE] adds MT942 compatibility
|
41
|
+
- `[FEATURE]` adds MT942 compatibility
|
14
42
|
|
15
43
|
# 1.2.0
|
16
44
|
|
17
|
-
- [FEATURE] strips mt940 header if configured ([#9](https://github.com/railslove/cmxl/issues/9))
|
45
|
+
- `[FEATURE]` strips mt940 header if configured ([#9](https://github.com/railslove/cmxl/issues/9))
|
18
46
|
```ruby
|
19
47
|
Cmxl.config[:strip_headers] = true
|
20
48
|
```
|
21
49
|
|
22
50
|
# 1.1.1
|
23
51
|
|
24
|
-
- [BUGFIX] prevents short bank references from swallowing supplementary details delimiter
|
52
|
+
- `[BUGFIX]` prevents short bank references from swallowing supplementary details delimiter
|
25
53
|
|
26
54
|
# 1.1.0
|
27
55
|
|
28
|
-
- [FEATURE] adds support for supplementary details in transactions (Field 61, Subfield 9) ([#18](https://github.com/railslove/cmxl/issues/18))
|
56
|
+
- `[FEATURE]` adds support for supplementary details in transactions (Field 61, Subfield 9) ([#18](https://github.com/railslove/cmxl/issues/18))
|
29
57
|
|
30
58
|
# 1.0.0
|
31
59
|
|
32
|
-
- [FEATURE] adds support for storno transactions ([#14](https://github.com/railslove/cmxl/issues/14))
|
33
|
-
- [NOTE] full backwards compatibility
|
34
|
-
- [NOTE] same as release 0.2.2, fixing versioning
|
60
|
+
- `[FEATURE]` adds support for storno transactions ([#14](https://github.com/railslove/cmxl/issues/14))
|
61
|
+
- `[NOTE]` full backwards compatibility
|
62
|
+
- `[NOTE]` same as release 0.2.2, fixing versioning
|
35
63
|
|
36
64
|
# 0.2.1
|
37
65
|
|
@@ -48,8 +76,8 @@
|
|
48
76
|
|
49
77
|
# 0.1.3
|
50
78
|
|
51
|
-
- [BUGFIX] fixed the statement details parser. It failed in case of empty values in the SEPA details
|
79
|
+
- `[BUGFIX]` fixed the statement details parser. It failed in case of empty values in the SEPA details
|
52
80
|
|
53
81
|
# 0.1.2
|
54
82
|
|
55
|
-
- [BUGFIX] fixed the statement details parser. It failed in case of empty values in the sub fields
|
83
|
+
- `[BUGFIX]` fixed the statement details parser. It failed in case of empty values in the sub fields
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
[](https://travis-ci.org/railslove/cmxl)
|
2
|
+
[](http://badge.fury.io/rb/cmxl)
|
2
3
|
|
3
4
|
# Cmxl - your friendly ruby MT940 parser
|
4
5
|
|
5
6
|
At [Railslove](http://railslove.com) we build a lot of financial applications and work on integrating applications with banks and banking functionality.
|
6
7
|
Our goal is to make simple solutions for what often looks complicated.
|
7
8
|
|
8
|
-
Cmxl is a friendly and
|
9
|
+
Cmxl is a friendly and extensible MT940 bank statement file parser that helps you extract data from bank statement files.
|
9
10
|
|
10
11
|
## What is MT940 & MT942?
|
11
12
|
|
@@ -13,13 +14,13 @@ MT940 (MT = Message Type) is the SWIFT-Standard for the electronic transfer of b
|
|
13
14
|
When integrating with banks you often get MT940 or MT942 files as interface.
|
14
15
|
For more information have a look at the different [SWIFT message types](http://en.wikipedia.org/wiki/SWIFT_message_types)
|
15
16
|
|
16
|
-
At some point in the future MT940 file should be exchanged with newer XML documents - but banking institutions are slow so MT940 will stick around for a while.
|
17
|
+
At some point in the future MT940 file should be exchanged with newer XML documents - but banking institutions are slow, so MT940 will stick around for a while.
|
17
18
|
|
18
19
|
## Reqirements
|
19
20
|
|
20
21
|
Cmxl is a pure ruby parser and has no dependency on native extensions.
|
21
22
|
|
22
|
-
- Ruby
|
23
|
+
- Ruby (current officially supported distributions)
|
23
24
|
|
24
25
|
## Installation
|
25
26
|
|
@@ -49,7 +50,7 @@ Cmxl.config[:statement_separator] = /\n-.\n/m
|
|
49
50
|
# do you want an error to be raised when a line can not be parsed? default is true
|
50
51
|
Cmxl.config[:raise_line_format_errors] = true
|
51
52
|
|
52
|
-
# try to stip the SWIFT header data. This strips everything until the actual first MT940 field. (if parsing fails try this!)
|
53
|
+
# try to stip the SWIFT header data. This strips everything until the actual first MT940 field. (if parsing fails, try this!)
|
53
54
|
Cmxl.config[:strip_headers] = true
|
54
55
|
|
55
56
|
|
@@ -61,7 +62,7 @@ statements.each do |s|
|
|
61
62
|
puts s.generation_date
|
62
63
|
puts s.opening_balance.amount
|
63
64
|
puts s.closing_balance.amount
|
64
|
-
puts s.sha # SHA of the statement source - could be used as an
|
65
|
+
puts s.sha # SHA of the statement source - could be used as an identifier (see: https://github.com/railslove/cmxl/blob/master/lib/cmxl/statement.rb#L49-L55)
|
65
66
|
|
66
67
|
s.transactions.each do |t|
|
67
68
|
puts t.information
|
@@ -83,14 +84,14 @@ end
|
|
83
84
|
|
84
85
|
```
|
85
86
|
|
86
|
-
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
|
87
|
+
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 favorite JSON library.
|
87
88
|
|
88
|
-
#### A note about encoding and file
|
89
|
+
#### A note about encoding and file weirdnesses
|
89
90
|
|
90
91
|
You probably will encounter encoding issues (hey, you are building banking applications!).
|
91
|
-
We try to handle encoding and format
|
92
|
-
In the likely case that you
|
93
|
-
If that fails try to
|
92
|
+
We try to handle encoding and format weirdnesses as much as possible. If no encoding is passed we try to guess the encoding of the data and convert it to UTF8.
|
93
|
+
In the likely case that you encounter encoding issues you can pass encoding options to `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)
|
94
|
+
If that fails, try to modify the file before you pass it to the parser - and please create an issue.
|
94
95
|
|
95
96
|
### MT940 SWIFT header data
|
96
97
|
|
@@ -184,13 +185,8 @@ other parsers:
|
|
184
185
|
- [betterplace/mt940_parser](https://github.com/betterplace/mt940_parser)
|
185
186
|
- [gmitrev/mt940parser](https://github.com/gmitrev/mt940parser)
|
186
187
|
|
187
|
-
## Stats
|
188
|
-
|
189
|
-
[](https://travis-ci.org/railslove/cmxl)
|
190
|
-
[](https://codeclimate.com/github/railslove/cmxl)
|
191
|
-
[](https://codeclimate.com/github/railslove/cmxl)
|
192
|
-
[](http://badge.fury.io/rb/cmxl)
|
193
|
-
|
194
188
|
---
|
189
|
+
built with love by [Railslove](http://railslove.com) and some [amazing people](https://github.com/railslove/cmxl/graphs/contributors).
|
190
|
+
Released under the MIT-Licence.
|
195
191
|
|
196
|
-
|
192
|
+
Railslove builds FinTech products, if you need support for your project we are happy to help. Please contact us at team@railslove.com.
|
data/lib/cmxl.rb
CHANGED
@@ -36,9 +36,9 @@ module Cmxl
|
|
36
36
|
end
|
37
37
|
|
38
38
|
if options[:encoding]
|
39
|
-
data.encode!('UTF-8', options.delete(:encoding), options)
|
39
|
+
data.encode!('UTF-8', options.delete(:encoding), **options)
|
40
40
|
else
|
41
|
-
data.encode!('UTF-8', options) unless options.empty?
|
41
|
+
data.encode!('UTF-8', **options) unless options.empty?
|
42
42
|
end
|
43
43
|
|
44
44
|
data.split(options[:statement_separator]).reject { |s| s.strip.empty? }.collect { |s| Cmxl::Statement.new(s.strip) }
|
@@ -2,7 +2,7 @@ module Cmxl
|
|
2
2
|
module Fields
|
3
3
|
class AccountBalance < Field
|
4
4
|
self.tag = 60
|
5
|
-
self.parser = /(?<funds_code>\A[a-zA-Z]{1})(?<date>\d{6})(?<currency>[a-zA-Z]{3})(?<amount>[\d|,|\.]{
|
5
|
+
self.parser = /(?<funds_code>\A[a-zA-Z]{1})(?<date>\d{6})(?<currency>[a-zA-Z]{3})(?<amount>[\d|,|\.]{1,15})/i
|
6
6
|
|
7
7
|
def date
|
8
8
|
to_date(data['date'])
|
@@ -38,6 +38,10 @@ module Cmxl
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
def primanota
|
42
|
+
sub_fields['10']
|
43
|
+
end
|
44
|
+
|
41
45
|
def bic
|
42
46
|
sub_fields['30']
|
43
47
|
end
|
@@ -60,6 +64,7 @@ module Cmxl
|
|
60
64
|
'description' => description,
|
61
65
|
'sub_fields' => sub_fields,
|
62
66
|
'transaction_code' => transaction_code,
|
67
|
+
'primanota' => primanota,
|
63
68
|
'details' => details
|
64
69
|
}
|
65
70
|
end
|
@@ -2,7 +2,7 @@ module Cmxl
|
|
2
2
|
module Fields
|
3
3
|
class Transaction < Field
|
4
4
|
self.tag = 61
|
5
|
-
self.parser = %r{^(?<date>\d{6})(?<entry_date>\d{4})?(?<storno_flag>R?)(?<funds_code>[CD]{1})(?<currency_letter>[a-zA-Z])?(?<amount>\d{1,12},\d{0,2})(?<swift_code>(?:N|F).{3})(?<reference>NONREF|(.(?!\/\/)){,16}([^\/]){,1})((?:\/\/)(?<bank_reference>[^\n]{,16}))?((?:\n)(?<supplementary>.{,34}))?$}
|
5
|
+
self.parser = %r{^(?<date>\d{6})(?<entry_date>\d{4})?(?<storno_flag>R?)(?<funds_code>[CD]{1})(?<currency_letter>[a-zA-Z])?(?<amount>\d{1,12},\d{0,2})(?<swift_code>(?:N|F|S).{3})(?<reference>NONREF|(.(?!\/\/)){,16}([^\/]){,1})((?:\/\/)(?<bank_reference>[^\n]{,16}))?((?:\n)(?<supplementary>.{,34}))?$}
|
6
6
|
|
7
7
|
attr_accessor :details
|
8
8
|
|
@@ -126,6 +126,10 @@ module Cmxl
|
|
126
126
|
details.sub_fields if details
|
127
127
|
end
|
128
128
|
|
129
|
+
def primanota
|
130
|
+
details.primanota if details
|
131
|
+
end
|
132
|
+
|
129
133
|
def to_h
|
130
134
|
{
|
131
135
|
'sha' => sha,
|
data/lib/cmxl/statement.rb
CHANGED
@@ -26,7 +26,7 @@ module Cmxl
|
|
26
26
|
def parse!
|
27
27
|
self.fields = []
|
28
28
|
|
29
|
-
lines = source.split(/(
|
29
|
+
lines = source.split(/(^:[0-9A-Z]{2,3}:)/m).reject(&:empty?).each_slice(2).map(&:join)
|
30
30
|
|
31
31
|
lines.map do |line|
|
32
32
|
if line =~ /\A:86:/
|
@@ -58,8 +58,9 @@ module Cmxl
|
|
58
58
|
field(20).reference
|
59
59
|
end
|
60
60
|
|
61
|
+
#Get generation date from field 20. If generation date is not provided in field 20, method will fall back to field 13 if present.
|
61
62
|
def generation_date
|
62
|
-
field(20).date || field(13).date
|
63
|
+
field(20).date || (field(13).nil? ? nil : field(13).date)
|
63
64
|
end
|
64
65
|
|
65
66
|
def account_identification
|
data/lib/cmxl/version.rb
CHANGED
@@ -39,4 +39,11 @@ describe Cmxl::Fields::AccountBalance do
|
|
39
39
|
it { expect(subject.amount_in_cents).to eql(14_764) }
|
40
40
|
it { expect(subject.sign).to eql(-1) }
|
41
41
|
end
|
42
|
+
|
43
|
+
context 'broken debit' do
|
44
|
+
subject { Cmxl::Fields::AccountBalance.parse(fixture_line(:account_balance_debit_broken)) }
|
45
|
+
|
46
|
+
it { expect(subject.amount).to eql(0.0) }
|
47
|
+
it { expect(subject.amount_in_cents).to eql(0) }
|
48
|
+
end
|
42
49
|
end
|
@@ -70,6 +70,7 @@ describe Cmxl::Fields::StatementDetails do
|
|
70
70
|
'99' => ''
|
71
71
|
},
|
72
72
|
'transaction_code' => '171',
|
73
|
+
'primanota' => '281',
|
73
74
|
'details' => '?00SEPA LASTSCHRIFT KUNDE?10281?20KREF+EREF+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'
|
74
75
|
)
|
75
76
|
}
|
@@ -9,6 +9,7 @@ describe Cmxl::Fields::Transaction do
|
|
9
9
|
subject(:complex_supplementary_transaction) { Cmxl::Fields::Transaction.parse(fixture_line(:statement_supplementary_complex)) }
|
10
10
|
subject(:valuta_after_enty_date) { Cmxl::Fields::Transaction.parse(fixture[3]) }
|
11
11
|
subject(:entry_before_valuta_transaction) { Cmxl::Fields::Transaction.parse(fixture[2]) }
|
12
|
+
subject(:transaction_type_swift) { Cmxl::Fields::Transaction.parse(fixture[4]) }
|
12
13
|
|
13
14
|
let(:fixture) { fixture_line(:statement_line).split(/\n/) }
|
14
15
|
|
@@ -91,4 +92,19 @@ describe Cmxl::Fields::Transaction do
|
|
91
92
|
expect(valuta_after_enty_date.entry_date).to eql(Date.new(2015, 1, 2))
|
92
93
|
end
|
93
94
|
end
|
95
|
+
|
96
|
+
context 'transaction type swift transfer' do
|
97
|
+
it { expect(transaction_type_swift.date).to eql(Date.new(2019, 11, 18)) }
|
98
|
+
it { expect(transaction_type_swift.entry_date).to eql(Date.new(2019, 11, 18)) }
|
99
|
+
it { expect(transaction_type_swift.funds_code).to eql('C') }
|
100
|
+
it { expect(transaction_type_swift.currency_letter).to eql('R') }
|
101
|
+
it { expect(transaction_type_swift.amount).to eql(653.0) }
|
102
|
+
it { expect(transaction_type_swift.amount_in_cents).to eql(65300) }
|
103
|
+
it { expect(transaction_type_swift.swift_code).to eql('S445') }
|
104
|
+
it { expect(transaction_type_swift.reference).to eql('328556-76501096') }
|
105
|
+
it { expect(transaction_type_swift).to be_credit }
|
106
|
+
it { expect(transaction_type_swift).not_to be_debit }
|
107
|
+
it { expect(transaction_type_swift).not_to be_storno }
|
108
|
+
it { expect(transaction_type_swift.sign).to eql(1) }
|
109
|
+
end
|
94
110
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
:60F:D140829EUR0,
|
data/spec/fixtures/mt940.txt
CHANGED
@@ -74,3 +74,34 @@ Interest credit
|
|
74
74
|
:62F:C020325PLN50040,00
|
75
75
|
|
76
76
|
-
|
77
|
+
|
78
|
+
:20:01ANWZTPJTYEGJWA
|
79
|
+
:25:45050050/76198810
|
80
|
+
:28:27/01
|
81
|
+
:60F:C131016DEM84349,74
|
82
|
+
:61:131017D6800,NCHK16703074
|
83
|
+
:86:999PN5477SCHECK-NR. 0000016703074
|
84
|
+
:61:131017D620,3NSTON
|
85
|
+
:86:999PN0911DAUERAUFTR.NR. 14
|
86
|
+
:61:131017C18500,NCLRN
|
87
|
+
:86:999PN2406SCHECK
|
88
|
+
:61:131015D14220,NBOEN
|
89
|
+
:86:999PN0920WECHSEL
|
90
|
+
:61:131017D1507,NTRFN
|
91
|
+
:86:999PN0920SCHNELLUEB
|
92
|
+
:61:131024C4200,NMSCN
|
93
|
+
:86:999PN2506AUSSENH. NR. 1
|
94
|
+
:61:131017D19900,NTRFN
|
95
|
+
:86:999PN0907UEBERTRAG
|
96
|
+
:61:131017D400,NTRFN
|
97
|
+
:86:999PN0891BTX
|
98
|
+
:61:131018C3656,74NMSCN
|
99
|
+
:86:999PN0850EINZAHLG.N
|
100
|
+
:61:131019C23040,NMSCN
|
101
|
+
:86:999PN0812LT.ANLAGE
|
102
|
+
:61:131027D5862,14NCHKN
|
103
|
+
:86:999PN5329AUSLSCHECK
|
104
|
+
:62F:C131017DEM84437,04
|
105
|
+
|
106
|
+
-
|
107
|
+
|
data/spec/fixtures/mt942.txt
CHANGED
@@ -7,3 +7,15 @@
|
|
7
7
|
:86:008?00DAUERAUFTRAG?100599?20Miete Dezember?3010020030?31234567?32MUELLER?34339
|
8
8
|
:90D:0EUR0,00
|
9
9
|
:90C:1EUR9792,00
|
10
|
+
|
11
|
+
-
|
12
|
+
|
13
|
+
:20:01ANWZTPJTYEGJWA
|
14
|
+
:25:45050050/76198810
|
15
|
+
:28C:13/37
|
16
|
+
:34F:EURD12345,67
|
17
|
+
:13D:1901091733+0100
|
18
|
+
:61:190109C9792,00FTRFNONREF
|
19
|
+
:86:008?00DAUERAUFTRAG?100599?20Miete Dezember?3010020030?31234567?32MUELLER?34339
|
20
|
+
:90D:0EUR0,00
|
21
|
+
:90C:1EUR9792,00
|
@@ -1,2 +1,2 @@
|
|
1
1
|
:61:1409010902DR000000000001,62NTRF0000549855700010//025498557/000001
|
2
|
-
:86:171?00SEPA LASTSCHRIFT KUNDE?10281?20KREF+EREF+TRX-0A4A47C3-F846-4729?21-8A1B-5DF620F?
|
2
|
+
:86:171?00SEPA LASTSCHRIFT KUNDE?10281?20KREF+EREF+TRX-0A4A47C3-F846-4729?21-8A1B-5DF620F?22:FOO:MREF+CAC97D2144174318A?23BF815BD4FB?24CRED+DE98ZZZ09999999999?25SVWZ+FOO TRX-0A4A47C3-F84?266-4729-8A1B-5DF620F?30HYVEDEMMXXX?31HUkkbbbsssskcccccccccccccccx?32Peter Pan?99?34171
|
data/spec/mt940_parsing_spec.rb
CHANGED
@@ -61,11 +61,18 @@ describe 'parsing a statement' do
|
|
61
61
|
it { expect(subject.field('NS').to_h).to eql({tag: 'NS', modifier: 'F', source: 'HelloWorld'}) }
|
62
62
|
end
|
63
63
|
|
64
|
+
context 'no generation date' do
|
65
|
+
subject { Cmxl.parse(mt940_file('mt940'))[3] }
|
66
|
+
|
67
|
+
it { expect(subject.reference).to eql('01ANWZTPJTYEGJWA') }
|
68
|
+
it { expect(subject.generation_date).to eql(nil) }
|
69
|
+
end
|
70
|
+
|
64
71
|
context 'statement separator as used by most banks' do
|
65
72
|
subject { Cmxl.parse(mt940_file('mt940')) }
|
66
73
|
|
67
74
|
it 'detects all statements by default' do
|
68
|
-
expect(subject.size).to eq(
|
75
|
+
expect(subject.size).to eq(4)
|
69
76
|
end
|
70
77
|
end
|
71
78
|
|
data/spec/statement_spec.rb
CHANGED
@@ -13,6 +13,7 @@ describe Cmxl do
|
|
13
13
|
it { expect(subject.entry_date).to eql(Date.new(2014, 9, 2)) }
|
14
14
|
it { expect(subject.amount).to eql(1.62) }
|
15
15
|
it { expect(subject.amount_in_cents).to eql(162) }
|
16
|
+
it { expect(subject.primanota).to eql('281') }
|
16
17
|
it {
|
17
18
|
expect(subject.to_h).to eql(
|
18
19
|
'date' => Date.new(2014, 9, 1),
|
@@ -34,19 +35,19 @@ describe Cmxl do
|
|
34
35
|
'name' => 'Peter Pan',
|
35
36
|
'sepa' => {
|
36
37
|
'KREF' => '',
|
37
|
-
'EREF' => 'TRX-0A4A47C3-F846-4729-8A1B-5DF620F',
|
38
|
-
'MREF' => '
|
38
|
+
'EREF' => 'TRX-0A4A47C3-F846-4729-8A1B-5DF620F:FOO:',
|
39
|
+
'MREF' => 'CAC97D2144174318ABF815BD4FB',
|
39
40
|
'CRED' => 'DE98ZZZ09999999999',
|
40
41
|
'SVWZ' => 'FOO TRX-0A4A47C3-F846-4729-8A1B-5DF620F'
|
41
42
|
},
|
42
|
-
'information' => 'KREF+EREF+TRX-0A4A47C3-F846-4729-8A1B-
|
43
|
+
'information' => 'KREF+EREF+TRX-0A4A47C3-F846-4729-8A1B-5DF620F:FOO:MREF+CAC97D2144174318ABF815BD4FBCRED+DE98ZZZ09999999999SVWZ+FOO TRX-0A4A47C3-F846-4729-8A1B-5DF620F',
|
43
44
|
'description' => 'SEPA LASTSCHRIFT KUNDE',
|
44
45
|
'sub_fields' => {
|
45
46
|
'00' => 'SEPA LASTSCHRIFT KUNDE',
|
46
47
|
'10' => '281',
|
47
48
|
'20' => 'KREF+EREF+TRX-0A4A47C3-F846-4729',
|
48
49
|
'21' => '-8A1B-5DF620F',
|
49
|
-
'22' => 'MREF+
|
50
|
+
'22' => ':FOO:MREF+CAC97D2144174318A',
|
50
51
|
'23' => 'BF815BD4FB',
|
51
52
|
'24' => 'CRED+DE98ZZZ09999999999',
|
52
53
|
'25' => 'SVWZ+FOO TRX-0A4A47C3-F84',
|
@@ -58,7 +59,8 @@ describe Cmxl do
|
|
58
59
|
'34' => '171'
|
59
60
|
},
|
60
61
|
'transaction_code' => '171',
|
61
|
-
'
|
62
|
+
'primanota' => '281',
|
63
|
+
'details' => '?00SEPA LASTSCHRIFT KUNDE?10281?20KREF+EREF+TRX-0A4A47C3-F846-4729?21-8A1B-5DF620F?22:FOO:MREF+CAC97D2144174318A?23BF815BD4FB?24CRED+DE98ZZZ09999999999?25SVWZ+FOO TRX-0A4A47C3-F84?266-4729-8A1B-5DF620F?30HYVEDEMMXXX?31HUkkbbbsssskcccccccccccccccx?32Peter Pan?99?34171'
|
62
64
|
)
|
63
65
|
}
|
64
66
|
end
|
@@ -143,4 +145,20 @@ describe Cmxl do
|
|
143
145
|
expect(subject.transactions.first.iban).to eq('234567')
|
144
146
|
end
|
145
147
|
end
|
148
|
+
|
149
|
+
context 'mt942 generation date from field 20' do
|
150
|
+
subject(:statement) { Cmxl.parse(mt940_file('mt942')).first }
|
151
|
+
|
152
|
+
it { expect(statement.mt942?).to be_truthy }
|
153
|
+
it { expect(statement.generation_date).to eql(Date.new(2013, 11, 10)) }
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'mt942 generation date from field 13' do
|
158
|
+
subject(:statement) { Cmxl.parse(mt940_file('mt942'))[1] }
|
159
|
+
|
160
|
+
it { expect(statement.mt942?).to be_truthy }
|
161
|
+
it { expect(statement.generation_date).to eql(Date.new(2019, 1, 9)) }
|
162
|
+
end
|
163
|
+
|
146
164
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cmxl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Bumann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -143,6 +143,7 @@ files:
|
|
143
143
|
- spec/fields/vmk_summary_spec.rb
|
144
144
|
- spec/fixtures/lines/account_balance_credit.txt
|
145
145
|
- spec/fixtures/lines/account_balance_debit.txt
|
146
|
+
- spec/fixtures/lines/account_balance_debit_broken.txt
|
146
147
|
- spec/fixtures/lines/account_identification_iban.txt
|
147
148
|
- spec/fixtures/lines/account_identification_legacy.txt
|
148
149
|
- spec/fixtures/lines/available_balance.txt
|
@@ -197,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
197
198
|
- !ruby/object:Gem::Version
|
198
199
|
version: '0'
|
199
200
|
requirements: []
|
200
|
-
rubygems_version: 3.
|
201
|
+
rubygems_version: 3.1.2
|
201
202
|
signing_key:
|
202
203
|
specification_version: 4
|
203
204
|
summary: Cmxl is your friendly MT940 bank statement parser
|
@@ -218,6 +219,7 @@ test_files:
|
|
218
219
|
- spec/fields/vmk_summary_spec.rb
|
219
220
|
- spec/fixtures/lines/account_balance_credit.txt
|
220
221
|
- spec/fixtures/lines/account_balance_debit.txt
|
222
|
+
- spec/fixtures/lines/account_balance_debit_broken.txt
|
221
223
|
- spec/fixtures/lines/account_identification_iban.txt
|
222
224
|
- spec/fixtures/lines/account_identification_legacy.txt
|
223
225
|
- spec/fixtures/lines/available_balance.txt
|