cmxl 0.1.3 → 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.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.mdown +5 -0
- data/cmxl.gemspec +1 -0
- data/lib/cmxl.rb +3 -3
- data/lib/cmxl/field.rb +4 -0
- data/lib/cmxl/fields/{statement_line.rb → transaction.rb} +45 -2
- data/lib/cmxl/statement.rb +39 -8
- data/lib/cmxl/version.rb +1 -1
- data/spec/fields/{statment_line_spec.rb → transaction_spec.rb} +2 -2
- data/spec/fixtures/mt940-deutsche_bank.txt +70 -0
- data/spec/fixtures/mt940-with-detailed-end-balance.txt +8 -0
- data/spec/fixtures/statement-details-mt940.txt +2 -0
- data/spec/fixtures/statement-mt940.txt +1 -0
- data/spec/mt940_parsing_spec.rb +19 -6
- data/spec/spec_helper.rb +2 -2
- data/spec/{transaction_spec.rb → statement_spec.rb} +41 -13
- metadata +31 -9
- data/lib/cmxl/transaction.rb +0 -98
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 42504a4554682fd712473e3e744db2892083965e
|
4
|
+
data.tar.gz: 3830a7a989cb7f5d490122d2079e67a45dcc75a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4fc0b6927125e065f9c5b9f8c15f2e6ee7d35feb938a72f9bfde9e059e672389e2a00c6e747e81dacf50ca062a8eb1dd39cac7c30272d40fd282022124ddd56a
|
7
|
+
data.tar.gz: f64a53ecbf51cedbaf80fdcad20a9e0e1aa47bd9780cb05768401d3449756344ad4956e4bb4eaef10bfe2851409b72c95cdc6ba0298582a95a51ce1568c1d766
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
CHANGED
data/CHANGELOG.mdown
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
# 0.2.0
|
2
|
+
* added several balance related accessors (#7)
|
3
|
+
* configuration option for `statement separator` (#5)
|
4
|
+
* improvement for general compatibility
|
5
|
+
|
1
6
|
# 0.1.3
|
2
7
|
|
3
8
|
* [BUGFIX] fixed the statement details parser. It failed in case of empty values in the SEPA details
|
data/cmxl.gemspec
CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.5"
|
24
24
|
spec.add_development_dependency "rake"
|
25
25
|
spec.add_development_dependency "rspec", '~>3.0'
|
26
|
+
spec.add_development_dependency "simplecov"
|
26
27
|
|
27
28
|
spec.add_dependency "rchardet19"
|
28
29
|
end
|
data/lib/cmxl.rb
CHANGED
@@ -4,14 +4,13 @@ require "rchardet19"
|
|
4
4
|
|
5
5
|
require 'cmxl/field'
|
6
6
|
require 'cmxl/statement'
|
7
|
-
require 'cmxl/transaction'
|
8
7
|
Dir[File.join(File.dirname(__FILE__), 'cmxl/fields', '*.rb')].each { |f| require f; }
|
9
8
|
|
10
9
|
module Cmxl
|
11
10
|
def self.config
|
12
11
|
@config
|
13
12
|
end
|
14
|
-
@config = { :statement_separator => /\n
|
13
|
+
@config = { :statement_separator => /\n-\s*\n/m, :raise_line_format_errors => true }
|
15
14
|
|
16
15
|
# Public: Parse a MT940 string
|
17
16
|
#
|
@@ -27,6 +26,7 @@ module Cmxl
|
|
27
26
|
# Returns an array of Statement objects
|
28
27
|
def self.parse(data, options={})
|
29
28
|
options[:universal_newline] ||= true
|
29
|
+
options[:statement_separator] ||= self.config[:statement_separator]
|
30
30
|
# if no encoding is provided we try to guess using CharDet
|
31
31
|
if options[:encoding].nil? && cd = CharDet.detect(data, silent: true)
|
32
32
|
options[:encoding] = cd.encoding
|
@@ -38,6 +38,6 @@ module Cmxl
|
|
38
38
|
data.encode!('UTF-8', options) if !options.empty?
|
39
39
|
end
|
40
40
|
|
41
|
-
data.split(
|
41
|
+
data.split(options[:statement_separator]).reject { |s| s.strip.empty? }.collect {|s| Cmxl::Statement.new(s.strip) }
|
42
42
|
end
|
43
43
|
end
|
data/lib/cmxl/field.rb
CHANGED
@@ -1,9 +1,19 @@
|
|
1
1
|
module Cmxl
|
2
2
|
module Fields
|
3
|
-
class
|
3
|
+
class Transaction < Field
|
4
4
|
self.tag = 61
|
5
5
|
self.parser = /^(?<date>\d{6})(?<entry_date>\d{4})?(?<funds_code>[a-zA-Z])(?<currency_letter>[a-zA-Z])?(?<amount>\d{1,12},\d{0,2})(?<swift_code>(?:N|F).{3})(?<reference>NONREF|.{0,16})(?:$|\/\/)(?<bank_reference>.*)/i
|
6
6
|
|
7
|
+
attr_accessor :details
|
8
|
+
|
9
|
+
def add_meta_data(content)
|
10
|
+
self.details = Cmxl::Fields::StatementDetails.parse(content) unless content.nil?
|
11
|
+
end
|
12
|
+
|
13
|
+
def sha
|
14
|
+
Digest::SHA2.new.update(source).to_s
|
15
|
+
end
|
16
|
+
|
7
17
|
def credit?
|
8
18
|
self.data['funds_code'].to_s.upcase == 'C'
|
9
19
|
end
|
@@ -31,8 +41,33 @@ module Cmxl
|
|
31
41
|
to_date(self.data['entry_date'], self.date.year) if self.data['entry_date'] && self.date
|
32
42
|
end
|
33
43
|
|
44
|
+
# Fields from details
|
45
|
+
|
46
|
+
def description
|
47
|
+
details.description if details
|
48
|
+
end
|
49
|
+
def information
|
50
|
+
details.information if details
|
51
|
+
end
|
52
|
+
def bic
|
53
|
+
details.bic if details
|
54
|
+
end
|
55
|
+
def name
|
56
|
+
details.name if details
|
57
|
+
end
|
58
|
+
def iban
|
59
|
+
details.iban if details
|
60
|
+
end
|
61
|
+
def sepa
|
62
|
+
details.sepa if details
|
63
|
+
end
|
64
|
+
def sub_fields
|
65
|
+
details.sub_fields if details
|
66
|
+
end
|
67
|
+
|
34
68
|
def to_h
|
35
69
|
{
|
70
|
+
'sha' => sha,
|
36
71
|
'date' => date,
|
37
72
|
'entry_date' => entry_date,
|
38
73
|
'amount' => amount,
|
@@ -45,7 +80,15 @@ module Cmxl
|
|
45
80
|
'reference' => reference,
|
46
81
|
'bank_reference' => bank_reference,
|
47
82
|
'currency_letter' => currency_letter
|
48
|
-
}
|
83
|
+
}.merge(details ? details.to_h : {})
|
84
|
+
end
|
85
|
+
|
86
|
+
def to_hash
|
87
|
+
to_h
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_json(*args)
|
91
|
+
to_h.to_json(*args)
|
49
92
|
end
|
50
93
|
end
|
51
94
|
end
|
data/lib/cmxl/statement.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'digest/sha2'
|
2
2
|
module Cmxl
|
3
3
|
class Statement
|
4
|
-
attr_accessor :source, :collection, :
|
4
|
+
attr_accessor :source, :collection, :fields, :lines
|
5
5
|
|
6
6
|
# Public: Initiate a new Statement and parse a provided single statement string
|
7
7
|
# It directly parses the source and initiates file and transaction objects.
|
@@ -13,10 +13,13 @@ module Cmxl
|
|
13
13
|
self.source = source
|
14
14
|
self.fields = []
|
15
15
|
self.lines = []
|
16
|
-
self.transactions = []
|
17
16
|
self.parse!
|
18
17
|
end
|
19
18
|
|
19
|
+
def transactions
|
20
|
+
self.fields.select { |field| field.kind_of?(Fields::Transaction) }
|
21
|
+
end
|
22
|
+
|
20
23
|
# Internal: Parse a single MT940 statement and extract the line data
|
21
24
|
#
|
22
25
|
def parse!
|
@@ -28,17 +31,33 @@ module Cmxl
|
|
28
31
|
self.lines.last << line.strip
|
29
32
|
end
|
30
33
|
end
|
31
|
-
|
32
|
-
self.
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
|
35
|
+
self.fields = []
|
36
|
+
lines.each do |line|
|
37
|
+
if line.match(/\A:86:/)
|
38
|
+
if field = fields.last
|
39
|
+
field.add_meta_data(line)
|
40
|
+
end
|
37
41
|
else
|
38
42
|
field = Field.parse(line)
|
39
43
|
self.fields << field unless field.nil?
|
40
44
|
end
|
41
45
|
end
|
46
|
+
|
47
|
+
# puts "Fixed Fields"
|
48
|
+
# puts fields.inspect
|
49
|
+
#
|
50
|
+
# # Now we check each line for its content ans structure it for further use. If it is part of a transaction we initate or update a transaction else we parse the field and add it to the fields collection
|
51
|
+
# self.lines.each do |line|
|
52
|
+
# if line.match(/\A:61:/)
|
53
|
+
# self.transactions << Cmxl::Transaction.new(line)
|
54
|
+
# elsif line.match(/\A:86:/) && !self.transactions.last.nil?
|
55
|
+
# self.transactions.last.details = line
|
56
|
+
# else
|
57
|
+
# field = Field.parse(line)
|
58
|
+
# self.fields << field unless field.nil?
|
59
|
+
# end
|
60
|
+
# end
|
42
61
|
end
|
43
62
|
|
44
63
|
# Public: SHA2 of the provided source
|
@@ -65,14 +84,26 @@ module Cmxl
|
|
65
84
|
self.field(60, 'F')
|
66
85
|
end
|
67
86
|
|
87
|
+
def opening_or_intermediary_balance
|
88
|
+
self.field(60)
|
89
|
+
end
|
90
|
+
|
68
91
|
def closing_balance
|
69
92
|
self.field(62, 'F')
|
70
93
|
end
|
71
94
|
|
95
|
+
def closing_or_intermediary_balance
|
96
|
+
self.field(62)
|
97
|
+
end
|
98
|
+
|
72
99
|
def available_balance
|
73
100
|
self.field(64)
|
74
101
|
end
|
75
102
|
|
103
|
+
def legal_sequence_number
|
104
|
+
self.field(28).source
|
105
|
+
end
|
106
|
+
|
76
107
|
def to_h
|
77
108
|
{
|
78
109
|
'reference' => reference,
|
data/lib/cmxl/version.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Cmxl::Fields::
|
3
|
+
describe Cmxl::Fields::Transaction do
|
4
4
|
|
5
|
-
subject { Cmxl::Fields::
|
5
|
+
subject { Cmxl::Fields::Transaction.parse(fixture_line(:statement_line)) }
|
6
6
|
|
7
7
|
it { expect(subject.date).to eql(Date.new(2014,9,1)) }
|
8
8
|
it { expect(subject.entry_date).to eql(Date.new(2014,9,2)) }
|
@@ -0,0 +1,70 @@
|
|
1
|
+
:20:131110
|
2
|
+
:25:45050050/76198810
|
3
|
+
:28:27/01
|
4
|
+
:60F:C131016DEM84349,74
|
5
|
+
:61:131017D6800,NCHK16703074
|
6
|
+
:86:999PN5477SCHECK-NR. 0000016703074
|
7
|
+
:61:131017D620,3NSTON
|
8
|
+
:86:999PN0911DAUERAUFTR.NR. 14
|
9
|
+
:61:131017C18500,NCLRN
|
10
|
+
:86:999PN2406SCHECK
|
11
|
+
:61:131015D14220,NBOEN
|
12
|
+
:86:999PN0920WECHSEL
|
13
|
+
:61:131017D1507,NTRFN
|
14
|
+
:86:999PN0920SCHNELLUEB
|
15
|
+
:61:131024C4200,NMSCN
|
16
|
+
:86:999PN2506AUSSENH. NR. 1
|
17
|
+
:61:131017D19900,NTRFN
|
18
|
+
:86:999PN0907UEBERTRAG
|
19
|
+
:61:131017D400,NTRFN
|
20
|
+
:86:999PN0891BTX
|
21
|
+
:61:131018C3656,74NMSCN
|
22
|
+
:86:999PN0850EINZAHLG.N
|
23
|
+
:61:131019C23040,NMSCN
|
24
|
+
:86:999PN0812LT.ANLAGE
|
25
|
+
:61:131027D5862,14NCHKN
|
26
|
+
:86:999PN5329AUSLSCHECK
|
27
|
+
:62F:C131017DEM84437,04
|
28
|
+
-
|
29
|
+
:20:1234567
|
30
|
+
:21:9876543210
|
31
|
+
:25:10020030/1234567
|
32
|
+
:28C:5/1
|
33
|
+
:60F:C021101EUR2187,95
|
34
|
+
:61:0211011102DR800,NSTONONREF//55555
|
35
|
+
:86:008?00DAUERAUFTRAG?100599?20Miete November?3010020030?31234567?32MUELLER?34339
|
36
|
+
:61:0211021102CR3000,NTRFNONREF//55555
|
37
|
+
:86:051?00UEBERWEISUNG?100599?20Gehalt Oktob
|
38
|
+
er
|
39
|
+
?21Firma
|
40
|
+
Mustermann
|
41
|
+
GmbH?3050060400?31084756
|
42
|
+
4700?32MUELLER?34339
|
43
|
+
:62F:C021131EUR4387,95
|
44
|
+
-
|
45
|
+
:20:TELEWIZORY S.A.
|
46
|
+
:25:BPHKPLPK/320000546101
|
47
|
+
:28C:00084/001
|
48
|
+
:60F:C031002PLN40000,00
|
49
|
+
:61:0310201020C20000,00FMSCNONREF//8327000090031789
|
50
|
+
Card transaction
|
51
|
+
:86: 020?00Wyplata-(dysp/przel)?2008106000760000777777777777?2115617?
|
52
|
+
22INFO INFO INFO INFO INFO INFO 1 END?23INFO INFO INFO INFO INFO
|
53
|
+
INFO 2 END?24ZAPLATA ZA FABRYKATY DO TUB?25 - 200 S ZTUK, TRANZY
|
54
|
+
STORY-?26300 SZT GR544 I OPORNIKI-5?2700 SZT GTX847 FAKTURA 333/
|
55
|
+
2?28003.?3010600076?310000777777777777?32HUTA SZKLA TOPIC UL
|
56
|
+
PRZEMY?33SLOWA 67 32-669 WROCLAW?38PL081060007600007777777
|
57
|
+
77777
|
58
|
+
:61:0310201020D10000,00FTRFREF 25611247//8327000090031790
|
59
|
+
Transfer
|
60
|
+
:86: 020?00Wyplata-(dysp/przel)?2008106000760000777777777777?2115617?
|
61
|
+
22INFO INFO INFO INFO INFO INFO 1 END?23INFO INFO INFO INFO INFO
|
62
|
+
INFO 2 END?24ZAPLATA ZA FABRYKATY DO TUB?25 - 200 S ZTUK, TRANZY
|
63
|
+
STORY-?26300 SZT GR544 I OPORNIKI-5?2700 SZT GTX847 FAKTURA 333/
|
64
|
+
2?28003.?3010600076?310000777777777777?38PL081060007600007777777
|
65
|
+
77777
|
66
|
+
:61:0310201020C40,00FTRFNONREF//8327000090031791
|
67
|
+
Interest credit
|
68
|
+
:86: 844?00Uznanie kwotą odsetek?20Odsetki od lokaty nr 101000?21022086
|
69
|
+
:62F:C020325PLN50040,00
|
70
|
+
-
|
@@ -0,0 +1,8 @@
|
|
1
|
+
:20:STARTUMS
|
2
|
+
:25:45050050/76198810
|
3
|
+
:28C:00001/00001
|
4
|
+
:60F:C160101EUR10,00
|
5
|
+
:61:1601010222CR1,00NTRFNONREF//CT16-01-01-08.32
|
6
|
+
:86:008?00DAUERAUFTRAG?100599?20Miete Dezember?3010020030?31234567?32MUELLER?34339
|
7
|
+
:62F:C160222EUR15,00
|
8
|
+
:86:Some random addition to it
|
@@ -0,0 +1,2 @@
|
|
1
|
+
:61:1409010902DR000000000001,62NTRF0000549855700010//025498557/000001
|
2
|
+
:86:171?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
|
@@ -0,0 +1 @@
|
|
1
|
+
:61:1409010902DR000000000001,62NTRF0000549855700010//025498557/000001
|
data/spec/mt940_parsing_spec.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
3
2
|
require 'spec_helper'
|
4
3
|
|
5
4
|
describe 'parsing a statement' do
|
6
|
-
|
7
5
|
context 'ISO 8859-1' do
|
8
6
|
subject { Cmxl.parse(mt940_file('mt940-iso8859-1'))[0] }
|
7
|
+
|
9
8
|
it { expect(subject.reference).to eql('1234567') }
|
10
9
|
it { expect(subject.opening_balance.amount_in_cents).to eql(218795) }
|
11
10
|
it { expect(subject.closing_balance.amount_in_cents).to eql(438795) }
|
@@ -17,12 +16,12 @@ describe 'parsing a statement' do
|
|
17
16
|
|
18
17
|
context 'first example' do
|
19
18
|
subject { Cmxl.parse(mt940_file(), :encoding => 'ISO-8859-1', :universal_newline => true)[0] }
|
19
|
+
|
20
20
|
it { expect(subject.reference).to eql('131110') }
|
21
21
|
it { expect(subject.opening_balance.amount_in_cents).to eql(8434974) }
|
22
22
|
it { expect(subject.closing_balance.amount_in_cents).to eql(8443704) }
|
23
23
|
it { expect(subject.generation_date).to eql(Date.new(2013, 11, 10)) }
|
24
24
|
it { expect(subject.transactions.count).to eql(11) }
|
25
|
-
|
26
25
|
it { expect(subject.transactions.first.description).to eql('PN5477SCHECK-NR. 0000016703074') }
|
27
26
|
it { expect(subject.transactions.first.information).to eql('PN5477SCHECK-NR. 0000016703074') }
|
28
27
|
it { expect(subject.transactions.first.sepa).to eql({}) }
|
@@ -31,6 +30,7 @@ describe 'parsing a statement' do
|
|
31
30
|
|
32
31
|
context 'second example' do
|
33
32
|
subject { Cmxl.parse(mt940_file(), :encoding => 'ISO-8859-1', :universal_newline => true)[1] }
|
33
|
+
|
34
34
|
it { expect(subject.reference).to eql('1234567') }
|
35
35
|
it { expect(subject.opening_balance.amount_in_cents).to eql(218795) }
|
36
36
|
it { expect(subject.closing_balance.amount_in_cents).to eql(438795) }
|
@@ -44,10 +44,9 @@ describe 'parsing a statement' do
|
|
44
44
|
it { expect(subject.transactions.first.iban).to eql('234567') }
|
45
45
|
end
|
46
46
|
|
47
|
-
|
48
|
-
|
49
47
|
context 'third example' do
|
50
48
|
subject { Cmxl.parse(mt940_file(), :encoding => 'ISO-8859-1', :universal_newline => true)[2] }
|
49
|
+
|
51
50
|
it { expect(subject.reference).to eql('TELEWIZORY S.A.') }
|
52
51
|
it { expect(subject.opening_balance.amount_in_cents).to eql(4000000) }
|
53
52
|
it { expect(subject.closing_balance.amount_in_cents).to eql(5004000) }
|
@@ -59,7 +58,21 @@ describe 'parsing a statement' do
|
|
59
58
|
it { expect(subject.transactions.first.bic).to eql('10600076') }
|
60
59
|
it { expect(subject.transactions.first.iban).to eql('PL08106000760000777777777777') }
|
61
60
|
it { expect(subject.transactions.first.sepa).to eql({}) }
|
62
|
-
end
|
61
|
+
end
|
63
62
|
|
63
|
+
context 'statement separator as used by most banks' do
|
64
|
+
subject { Cmxl.parse(mt940_file('mt940')) }
|
64
65
|
|
66
|
+
it 'detects all statements by default' do
|
67
|
+
expect(subject.size).to eq(3)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'statement separator as used by Deutsche Bank' do
|
72
|
+
subject { Cmxl.parse(mt940_file('mt940-deutsche_bank')) }
|
73
|
+
|
74
|
+
it 'detects all statements by default' do
|
75
|
+
expect(subject.size).to eq(3)
|
76
|
+
end
|
77
|
+
end
|
65
78
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Cmxl
|
3
|
+
describe Cmxl do
|
4
4
|
|
5
5
|
context 'with details' do
|
6
|
-
subject { Cmxl
|
6
|
+
subject { Cmxl.parse( mt940_file('statement-details-mt940') ).first.transactions.first }
|
7
|
+
|
7
8
|
it { expect(subject).to be_debit }
|
8
9
|
it { expect(subject).to_not be_credit }
|
9
10
|
it { expect(subject.funds_code).to eql('D') }
|
10
|
-
it { expect(subject.date).to eql(Date.new(2014,9,1))}
|
11
|
-
it { expect(subject.entry_date).to eql(Date.new(2014,9,2))}
|
12
|
-
it { expect(subject.amount).to eql(1.62)}
|
13
|
-
it { expect(subject.
|
14
|
-
it { expect(subject.amount_in_cents).to eql(162)}
|
11
|
+
it { expect(subject.date).to eql(Date.new(2014,9,1)) }
|
12
|
+
it { expect(subject.entry_date).to eql(Date.new(2014,9,2)) }
|
13
|
+
it { expect(subject.amount).to eql(1.62) }
|
14
|
+
it { expect(subject.amount_in_cents).to eql(162) }
|
15
15
|
it { expect(subject.to_h).to eql(
|
16
16
|
{
|
17
17
|
"date" => Date.new(2014,9,1),
|
@@ -63,14 +63,42 @@ describe Cmxl::Transaction do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
context 'without details' do
|
66
|
-
subject { Cmxl
|
66
|
+
subject { Cmxl.parse( mt940_file('statement-mt940') ).first.transactions.first }
|
67
|
+
|
67
68
|
it { expect(subject).to be_debit }
|
68
69
|
it { expect(subject).to_not be_credit }
|
69
70
|
it { expect(subject.date).to eql(Date.new(2014,9,1))}
|
70
|
-
it { expect(subject.entry_date).to eql(Date.new(2014,9,2))}
|
71
|
-
it { expect(subject.amount).to eql(1.62)}
|
72
|
-
it { expect(subject.amount_in_cents).to eql(162)}
|
73
|
-
it
|
74
|
-
|
71
|
+
it { expect(subject.entry_date).to eql(Date.new(2014,9,2)) }
|
72
|
+
it { expect(subject.amount).to eql(1.62) }
|
73
|
+
it { expect(subject.amount_in_cents).to eql(162) }
|
74
|
+
it 'does not include any details in its hash representation' do
|
75
|
+
expect(subject.to_h).to eql({
|
76
|
+
"date" => Date.new(2014,9,1),
|
77
|
+
"sha" => "3c5e65aa3d3878b06b58b6f1ae2f3693004dfb04e3ab7119a1c1244e612293da",
|
78
|
+
"entry_date"=>Date.new(2014,9,2),
|
79
|
+
"funds_code" => "D",
|
80
|
+
"currency_letter" => "R",
|
81
|
+
"amount" => 1.62,
|
82
|
+
"swift_code" => "NTRF",
|
83
|
+
"reference" => "0000549855700010",
|
84
|
+
"bank_reference" => "025498557/000001",
|
85
|
+
"amount_in_cents" => 162,
|
86
|
+
"sign" => -1,
|
87
|
+
"debit" => true,
|
88
|
+
"credit" => false
|
89
|
+
})
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe 'statement with detailed end balance' do
|
94
|
+
subject { Cmxl.parse( mt940_file('mt940-with-detailed-end-balance') ).first.transactions.first }
|
95
|
+
|
96
|
+
it 'includes correct iban' do
|
97
|
+
expect(subject.iban).to eq('234567')
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'includes correct bic' do
|
101
|
+
expect(subject.bic).to eq('10020030')
|
102
|
+
end
|
75
103
|
end
|
76
104
|
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: 0.
|
4
|
+
version: 0.2.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: 2016-
|
11
|
+
date: 2016-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: simplecov
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rchardet19
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,6 +89,7 @@ extensions: []
|
|
75
89
|
extra_rdoc_files: []
|
76
90
|
files:
|
77
91
|
- ".gitignore"
|
92
|
+
- ".rspec"
|
78
93
|
- ".travis.yml"
|
79
94
|
- CHANGELOG.mdown
|
80
95
|
- Gemfile
|
@@ -90,10 +105,9 @@ files:
|
|
90
105
|
- lib/cmxl/fields/closing_balance.rb
|
91
106
|
- lib/cmxl/fields/reference.rb
|
92
107
|
- lib/cmxl/fields/statement_details.rb
|
93
|
-
- lib/cmxl/fields/statement_line.rb
|
94
108
|
- lib/cmxl/fields/statement_number.rb
|
109
|
+
- lib/cmxl/fields/transaction.rb
|
95
110
|
- lib/cmxl/statement.rb
|
96
|
-
- lib/cmxl/transaction.rb
|
97
111
|
- lib/cmxl/version.rb
|
98
112
|
- spec/field_spec.rb
|
99
113
|
- spec/fields/account_balance_spec.rb
|
@@ -103,7 +117,7 @@ files:
|
|
103
117
|
- spec/fields/reference_spec.rb
|
104
118
|
- spec/fields/statement_details_spec.rb
|
105
119
|
- spec/fields/statement_number_spec.rb
|
106
|
-
- spec/fields/
|
120
|
+
- spec/fields/transaction_spec.rb
|
107
121
|
- spec/fields/unknown_spec.rb
|
108
122
|
- spec/fixtures/lines/account_balance_credit.txt
|
109
123
|
- spec/fixtures/lines/account_balance_debit.txt
|
@@ -115,12 +129,16 @@ files:
|
|
115
129
|
- spec/fixtures/lines/statement_details.txt
|
116
130
|
- spec/fixtures/lines/statement_line.txt
|
117
131
|
- spec/fixtures/lines/statement_number.txt
|
132
|
+
- spec/fixtures/mt940-deutsche_bank.txt
|
118
133
|
- spec/fixtures/mt940-iso8859-1.txt
|
134
|
+
- spec/fixtures/mt940-with-detailed-end-balance.txt
|
119
135
|
- spec/fixtures/mt940.txt
|
136
|
+
- spec/fixtures/statement-details-mt940.txt
|
137
|
+
- spec/fixtures/statement-mt940.txt
|
120
138
|
- spec/mt940_parsing_spec.rb
|
121
139
|
- spec/spec_helper.rb
|
140
|
+
- spec/statement_spec.rb
|
122
141
|
- spec/support/fixtures.rb
|
123
|
-
- spec/transaction_spec.rb
|
124
142
|
homepage: https://github.com/railslove/cmxl
|
125
143
|
licenses:
|
126
144
|
- MIT
|
@@ -143,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
161
|
version: '0'
|
144
162
|
requirements: []
|
145
163
|
rubyforge_project:
|
146
|
-
rubygems_version: 2.
|
164
|
+
rubygems_version: 2.5.1
|
147
165
|
signing_key:
|
148
166
|
specification_version: 4
|
149
167
|
summary: Cmxl is your friendly MT940 bank statement parser
|
@@ -156,7 +174,7 @@ test_files:
|
|
156
174
|
- spec/fields/reference_spec.rb
|
157
175
|
- spec/fields/statement_details_spec.rb
|
158
176
|
- spec/fields/statement_number_spec.rb
|
159
|
-
- spec/fields/
|
177
|
+
- spec/fields/transaction_spec.rb
|
160
178
|
- spec/fields/unknown_spec.rb
|
161
179
|
- spec/fixtures/lines/account_balance_credit.txt
|
162
180
|
- spec/fixtures/lines/account_balance_debit.txt
|
@@ -168,9 +186,13 @@ test_files:
|
|
168
186
|
- spec/fixtures/lines/statement_details.txt
|
169
187
|
- spec/fixtures/lines/statement_line.txt
|
170
188
|
- spec/fixtures/lines/statement_number.txt
|
189
|
+
- spec/fixtures/mt940-deutsche_bank.txt
|
171
190
|
- spec/fixtures/mt940-iso8859-1.txt
|
191
|
+
- spec/fixtures/mt940-with-detailed-end-balance.txt
|
172
192
|
- spec/fixtures/mt940.txt
|
193
|
+
- spec/fixtures/statement-details-mt940.txt
|
194
|
+
- spec/fixtures/statement-mt940.txt
|
173
195
|
- spec/mt940_parsing_spec.rb
|
174
196
|
- spec/spec_helper.rb
|
197
|
+
- spec/statement_spec.rb
|
175
198
|
- spec/support/fixtures.rb
|
176
|
-
- spec/transaction_spec.rb
|
data/lib/cmxl/transaction.rb
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
module Cmxl
|
2
|
-
class Transaction
|
3
|
-
attr_accessor :statement_line, :details
|
4
|
-
|
5
|
-
def initialize(statement_line, details = nil)
|
6
|
-
self.statement_line = statement_line
|
7
|
-
self.details = details
|
8
|
-
end
|
9
|
-
|
10
|
-
def statement_line=(line)
|
11
|
-
@statement_line = Cmxl::Fields::StatementLine.parse(line) unless line.nil?
|
12
|
-
end
|
13
|
-
|
14
|
-
def details=(line)
|
15
|
-
@details = Cmxl::Fields::StatementDetails.parse(line) unless line.nil?
|
16
|
-
end
|
17
|
-
|
18
|
-
def sha
|
19
|
-
Digest::SHA2.new.update(self.statement_line.source).to_s
|
20
|
-
end
|
21
|
-
|
22
|
-
def debit?
|
23
|
-
self.statement_line.debit?
|
24
|
-
end
|
25
|
-
def credit?
|
26
|
-
self.statement_line.credit?
|
27
|
-
end
|
28
|
-
def amount
|
29
|
-
self.statement_line.amount
|
30
|
-
end
|
31
|
-
def sign
|
32
|
-
self.statement_line.sign
|
33
|
-
end
|
34
|
-
def funds_code
|
35
|
-
self.statement_line.funds_code
|
36
|
-
end
|
37
|
-
def amount_in_cents
|
38
|
-
self.statement_line.amount_in_cents
|
39
|
-
end
|
40
|
-
def date
|
41
|
-
self.statement_line.date
|
42
|
-
end
|
43
|
-
def entry_date
|
44
|
-
self.statement_line.entry_date
|
45
|
-
end
|
46
|
-
def funds_code
|
47
|
-
self.statement_line.funds_code
|
48
|
-
end
|
49
|
-
def currency_letter
|
50
|
-
self.statement_line.currency_letter
|
51
|
-
end
|
52
|
-
def swift_code
|
53
|
-
self.statement_line.swift_code
|
54
|
-
end
|
55
|
-
def reference
|
56
|
-
self.statement_line.reference
|
57
|
-
end
|
58
|
-
def bank_reference
|
59
|
-
self.statement_line.bank_reference
|
60
|
-
end
|
61
|
-
def description
|
62
|
-
self.details.description if self.details
|
63
|
-
end
|
64
|
-
def information
|
65
|
-
self.details.information if self.details
|
66
|
-
end
|
67
|
-
def bic
|
68
|
-
self.details.bic if self.details
|
69
|
-
end
|
70
|
-
def name
|
71
|
-
self.details.name if self.details
|
72
|
-
end
|
73
|
-
def iban
|
74
|
-
self.details.iban if self.details
|
75
|
-
end
|
76
|
-
def sepa
|
77
|
-
self.details.sepa if self.details
|
78
|
-
end
|
79
|
-
def sub_fields
|
80
|
-
self.details.sub_fields if self.details
|
81
|
-
end
|
82
|
-
|
83
|
-
def to_h
|
84
|
-
{}.tap do |h|
|
85
|
-
h['sha'] = self.sha
|
86
|
-
h.merge!(self.statement_line.to_h)
|
87
|
-
h.merge!(self.details.to_h) if self.details
|
88
|
-
end
|
89
|
-
end
|
90
|
-
def to_hash
|
91
|
-
to_h
|
92
|
-
end
|
93
|
-
def to_json(*args)
|
94
|
-
to_h.to_json(*args)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|