cmxl 2.0 → 2.1
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/.github/workflows/ci.yml +3 -2
- data/.rspec +2 -1
- data/CHANGELOG.mdown +6 -0
- data/README.md +1 -1
- data/lib/cmxl/statement.rb +2 -2
- data/lib/cmxl/version.rb +1 -1
- data/lib/cmxl.rb +5 -1
- data/spec/fixtures/mt940-abnamro.txt +44 -0
- data/spec/fixtures/mt940-handelsbank.txt +16 -0
- data/spec/fixtures/mt940-windows-line-breaks.txt +16 -0
- data/spec/mt940_parsing_spec.rb +111 -0
- data/spec/statement_spec.rb +85 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6114278dc458c8f3890f6f04e72a33915c98f235fe0694ba8d7b02cc5f394d6
|
4
|
+
data.tar.gz: d47ca765f53acf8f86d9c51b25123975174fc83c86cc68b834f069606ecd8cd4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ac2f348609babd4cca9df8da0412f965057fed77d210e155f076c489d407541effd6da7012b00ff48f642baec2ae96b028bad0720f08ff50c4f2327d34dc7bf
|
7
|
+
data.tar.gz: cfae7ffcf5ffe4ee50b2afac7828f712a9511e5e1da6493a17a7d94681094fee7729b2687ee5a9fdc9bad7e031778841ed8cda3db44c6741a6810c54f736d25a
|
data/.github/workflows/ci.yml
CHANGED
data/.rspec
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
--color
|
1
|
+
--color
|
2
|
+
--require 'pry'
|
data/CHANGELOG.mdown
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# NEXT release
|
2
2
|
|
3
|
+
# 2.1
|
4
|
+
- `[REFACTOR]` improve file parser to work with windows line breaks and any known header formats
|
5
|
+
- `[BUGFIX]` fix `strip_header` making it work on statements without headers
|
6
|
+
- `[HOUSEKEEPING]` use `main` instead of `master` as default branch
|
7
|
+
- `[ENHANCEMENT]` add support for ruby `3.4`
|
8
|
+
|
3
9
|
# 2.0
|
4
10
|
- `[REFACTOR]` **DEPRECATED:** `storno?` and related methods `storno_credit`, `storno_debit`. Use `reversal?` and related methods `reversal_credit?`, `reversal_debit?` instead
|
5
11
|
- `[BUGFIX]` **DEPRECATED:** `funds_code` method returns the `credit_debit_indicator` from the SWIFT definition. Therefore the method is deprecated in favor of `credit_debit_indicator` method
|
data/README.md
CHANGED
@@ -62,7 +62,7 @@ statements.each do |s|
|
|
62
62
|
puts s.generation_date
|
63
63
|
puts s.opening_balance.amount
|
64
64
|
puts s.closing_balance.amount
|
65
|
-
puts s.sha # SHA of the statement source - could be used as an identifier (see: https://github.com/railslove/cmxl/blob/
|
65
|
+
puts s.sha # SHA of the statement source - could be used as an identifier (see: https://github.com/railslove/cmxl/blob/main/lib/cmxl/statement.rb#L49-L55)
|
66
66
|
|
67
67
|
s.transactions.each do |t|
|
68
68
|
puts t.information
|
data/lib/cmxl/statement.rb
CHANGED
@@ -41,8 +41,8 @@ module Cmxl
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def strip_headers!
|
44
|
-
source.gsub!(/\A
|
45
|
-
source.gsub!(/^[^:]
|
44
|
+
source.gsub!(/\A.*?(?=^:)/m, '') # beginning: strip every line in the beginning that does not start with a :
|
45
|
+
source.gsub!(/^[^:]*\z/, '') # end: strip every line in the end that does not start with a :
|
46
46
|
source.strip!
|
47
47
|
end
|
48
48
|
|
data/lib/cmxl/version.rb
CHANGED
data/lib/cmxl.rb
CHANGED
@@ -11,7 +11,11 @@ module Cmxl
|
|
11
11
|
@config
|
12
12
|
end
|
13
13
|
@config = {
|
14
|
-
|
14
|
+
# One or more newlines
|
15
|
+
# followed by `-` at the beginning of a line.
|
16
|
+
# "Eats up" but does not require characters until the end of the line and more newlines.
|
17
|
+
# \R is a platform independent newline but in the negated group `[^\n\r]` that did not seem to work.
|
18
|
+
statement_separator: /\R+-[^\n\r]*\R*/m,
|
15
19
|
raise_line_format_errors: true,
|
16
20
|
strip_headers: false
|
17
21
|
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
ABNANL2A
|
2
|
+
940
|
3
|
+
ABNANL2A
|
4
|
+
:20:ABN AMRO BANK NV
|
5
|
+
:25:517852257
|
6
|
+
:28:19321/1
|
7
|
+
:60F:C110522EUR3236,28
|
8
|
+
:61:1105240524D9,N192NONREF
|
9
|
+
:86:GIRO 428428 KPN - DIGITENNE BETALINGSKENM. 000000042188659
|
10
|
+
5314606715 BETREFT FACTUUR D.D. 20-05-2011
|
11
|
+
INCL. 1,44 BTW
|
12
|
+
:61:1105210523D11,59N426NONREF
|
13
|
+
:86:BEA NR:XXX1234 21.05.11/12.54 DIRCKIII FIL2500 KATWIJK,PAS999
|
14
|
+
:61:1105230523D11,63N426NONREF
|
15
|
+
:86:BEA NR:XXX1234 23.05.11/09.08 DIGROS FIL1015 KATWIJK Z,PAS999
|
16
|
+
:61:1105220523D11,8N426NONREF
|
17
|
+
:86:BEA NR:XXX1234 22.05.11/14.25 MC DONALDS A44 LEIDEN,PAS999
|
18
|
+
:61:1105210523D13,45N426NONREF
|
19
|
+
:86:BEA NR:XXX1234 21.05.11/12.09 PRINCE FIL. 55 KATWIJK Z,PAS999
|
20
|
+
:61:1105210523D15,49N426NONREF
|
21
|
+
:86:BEA NR:XXX1234 21.05.11/12.55 DIRX FIL6017 KATWIJK ZH ,PAS999
|
22
|
+
|
23
|
+
:61:1105210523D107,N426NONREF
|
24
|
+
:86:BEA NR:XXX1234 21.05.11/12.04 HANS ANDERS OPT./056 KAT,PAS999
|
25
|
+
:61:1105220523D141,48N426NONREF
|
26
|
+
:86:BEA NR:XXX1234 22.05.11/13.45 MYCOM DEN HAAG S-GRAVEN,PAS999
|
27
|
+
:62F:C110523EUR876,84
|
28
|
+
|
29
|
+
-
|
30
|
+
|
31
|
+
ABNANL2A
|
32
|
+
940
|
33
|
+
ABNANL2A
|
34
|
+
:20:ABN AMRO BANK NV
|
35
|
+
:25:517852257
|
36
|
+
:28:19322/1
|
37
|
+
:60F:C110523EUR2876,84
|
38
|
+
:61:1105240524D9,49N426NONREF
|
39
|
+
:86:BEA NR:XXX1234 24.05.11/09.18 PETS PLACE KATWIJK KATWI,PAS999
|
40
|
+
:61:1105240524D15,N426NONREF
|
41
|
+
:86:52.89.39.882 MYCOM DEN HAAG S-GRAVEN,PAS999
|
42
|
+
:62F:C110524EUR1849,75
|
43
|
+
|
44
|
+
-
|
@@ -0,0 +1,16 @@
|
|
1
|
+
ä4:
|
2
|
+
:20:5566778899100112
|
3
|
+
:25:10020030/1234567
|
4
|
+
:28C:188/1
|
5
|
+
:60F:C130928SEK0,
|
6
|
+
:62F:C130930SEK0,
|
7
|
+
:64:C130930SEK0,
|
8
|
+
-å
|
9
|
+
ä4:
|
10
|
+
:20:5566778899100169
|
11
|
+
:25:10020030/1234567
|
12
|
+
:28C:188/1
|
13
|
+
:60F:C130928SEK0,
|
14
|
+
:62F:C130930SEK0,
|
15
|
+
:64:C130930SEK0,
|
16
|
+
-å
|
@@ -0,0 +1,16 @@
|
|
1
|
+
{1:D02AASDISLNETAXXXXXXXXXXXXX}
|
2
|
+
{2:E623XXXXXXXXAXXXN}
|
3
|
+
{4:
|
4
|
+
:20:1234567
|
5
|
+
:21:9876543210
|
6
|
+
:25:10020030/1234567
|
7
|
+
:28C:5/1
|
8
|
+
:60F:C160314EUR2187,95
|
9
|
+
:61:0211011102DR800,NSTONONREF//55555
|
10
|
+
:86:008?00DAUERAUFTRAG?100599?20Miete November?3010020030?31234567?32MUELLER?34339
|
11
|
+
:61:0211021102CR3000,NTRFNONREF//55555
|
12
|
+
:86:051?00UEBERWEISUNG?100599?20Gehalt Oktober?21Firma
|
13
|
+
Mustermann GmbH?3050060400?310847564700?32MUELLER?34339
|
14
|
+
:62F:C160315EUR4387,95
|
15
|
+
:86:Some random data
|
16
|
+
-}
|
data/spec/mt940_parsing_spec.rb
CHANGED
@@ -95,4 +95,115 @@ describe 'parsing a statement' do
|
|
95
95
|
expect(subject[0].transactions.count).to eql(1)
|
96
96
|
end
|
97
97
|
end
|
98
|
+
|
99
|
+
describe "MT940 abnamro" do
|
100
|
+
it "splits the file into on statement with the headers included" do
|
101
|
+
expected_data = <<~MT940.chomp
|
102
|
+
ABNANL2A
|
103
|
+
940
|
104
|
+
ABNANL2A
|
105
|
+
:20:ABN AMRO BANK NV
|
106
|
+
:25:517852257
|
107
|
+
:28:19321/1
|
108
|
+
:60F:C110522EUR3236,28
|
109
|
+
:61:1105240524D9,N192NONREF
|
110
|
+
:86:GIRO 428428 KPN - DIGITENNE BETALINGSKENM. 000000042188659
|
111
|
+
5314606715 BETREFT FACTUUR D.D. 20-05-2011
|
112
|
+
INCL. 1,44 BTW
|
113
|
+
:61:1105210523D11,59N426NONREF
|
114
|
+
:86:BEA NR:XXX1234 21.05.11/12.54 DIRCKIII FIL2500 KATWIJK,PAS999
|
115
|
+
:61:1105230523D11,63N426NONREF
|
116
|
+
:86:BEA NR:XXX1234 23.05.11/09.08 DIGROS FIL1015 KATWIJK Z,PAS999
|
117
|
+
:61:1105220523D11,8N426NONREF
|
118
|
+
:86:BEA NR:XXX1234 22.05.11/14.25 MC DONALDS A44 LEIDEN,PAS999
|
119
|
+
:61:1105210523D13,45N426NONREF
|
120
|
+
:86:BEA NR:XXX1234 21.05.11/12.09 PRINCE FIL. 55 KATWIJK Z,PAS999
|
121
|
+
:61:1105210523D15,49N426NONREF
|
122
|
+
:86:BEA NR:XXX1234 21.05.11/12.55 DIRX FIL6017 KATWIJK ZH ,PAS999
|
123
|
+
|
124
|
+
:61:1105210523D107,N426NONREF
|
125
|
+
:86:BEA NR:XXX1234 21.05.11/12.04 HANS ANDERS OPT./056 KAT,PAS999
|
126
|
+
:61:1105220523D141,48N426NONREF
|
127
|
+
:86:BEA NR:XXX1234 22.05.11/13.45 MYCOM DEN HAAG S-GRAVEN,PAS999
|
128
|
+
:62F:C110523EUR876,84
|
129
|
+
MT940
|
130
|
+
stub = instance_double(Cmxl::Statement)
|
131
|
+
allow(Cmxl::Statement).to receive(:new).and_return(stub)
|
132
|
+
|
133
|
+
Cmxl.parse(mt940_file('mt940-abnamro'))
|
134
|
+
|
135
|
+
expect(Cmxl::Statement).to have_received(:new).with(expected_data)
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'splits the file into two statements' do
|
139
|
+
allow(Cmxl::Statement).to receive(:new)
|
140
|
+
|
141
|
+
Cmxl.parse(mt940_file('mt940-abnamro'))
|
142
|
+
|
143
|
+
expect(Cmxl::Statement).to have_received(:new).twice
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe 'MT940 handelsbank' do
|
148
|
+
it 'splits the file with the special characters correctly' do
|
149
|
+
expected_data = <<~MT940.chomp
|
150
|
+
채4:
|
151
|
+
:20:5566778899100112
|
152
|
+
:25:10020030/1234567
|
153
|
+
:28C:188/1
|
154
|
+
:60F:C130928SEK0,
|
155
|
+
:62F:C130930SEK0,
|
156
|
+
:64:C130930SEK0,
|
157
|
+
MT940
|
158
|
+
stub = instance_double(Cmxl::Statement)
|
159
|
+
allow(Cmxl::Statement).to receive(:new).and_return(stub)
|
160
|
+
|
161
|
+
Cmxl.parse(mt940_file('mt940-handelsbank'))
|
162
|
+
|
163
|
+
expect(Cmxl::Statement).to have_received(:new).with(expected_data)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'splits the file into two statements' do
|
167
|
+
allow(Cmxl::Statement).to receive(:new)
|
168
|
+
|
169
|
+
Cmxl.parse(mt940_file('mt940-handelsbank'))
|
170
|
+
|
171
|
+
expect(Cmxl::Statement).to have_received(:new).twice
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "MT940 windows line breaks" do
|
176
|
+
it 'splits the file with the special characters correctly' do
|
177
|
+
expected_data =
|
178
|
+
"{1:D02AASDISLNETAXXXXXXXXXXXXX}\r\n"\
|
179
|
+
"{2:E623XXXXXXXXAXXXN}\r\n"\
|
180
|
+
"{4:\r\n"\
|
181
|
+
":20:1234567\r\n"\
|
182
|
+
":21:9876543210\r\n"\
|
183
|
+
":25:10020030/1234567\r\n"\
|
184
|
+
":28C:5/1\r\n"\
|
185
|
+
":60F:C160314EUR2187,95\r\n"\
|
186
|
+
":61:0211011102DR800,NSTONONREF//55555\r\n"\
|
187
|
+
":86:008?00DAUERAUFTRAG?100599?20Miete November?3010020030?31234567?32MUELLER?34339\r\n"\
|
188
|
+
":61:0211021102CR3000,NTRFNONREF//55555\r\n"\
|
189
|
+
":86:051?00UEBERWEISUNG?100599?20Gehalt Oktober?21Firma\r\n"\
|
190
|
+
"Mustermann GmbH?3050060400?310847564700?32MUELLER?34339\r\n"\
|
191
|
+
":62F:C160315EUR4387,95\r\n"\
|
192
|
+
":86:Some random data"
|
193
|
+
stub = instance_double(Cmxl::Statement)
|
194
|
+
allow(Cmxl::Statement).to receive(:new).and_return(stub)
|
195
|
+
|
196
|
+
Cmxl.parse(mt940_file('mt940-windows-line-breaks'))
|
197
|
+
|
198
|
+
expect(Cmxl::Statement).to have_received(:new).with(expected_data)
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'splits the file into two statements' do
|
202
|
+
allow(Cmxl::Statement).to receive(:new)
|
203
|
+
|
204
|
+
Cmxl.parse(mt940_file('mt940-windows-line-breaks'))
|
205
|
+
|
206
|
+
expect(Cmxl::Statement).to have_received(:new).once
|
207
|
+
end
|
208
|
+
end
|
98
209
|
end
|
data/spec/statement_spec.rb
CHANGED
@@ -101,7 +101,7 @@ describe Cmxl do
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
describe 'statement issued over a years
|
104
|
+
describe 'statement issued over a years boundary' do
|
105
105
|
subject { Cmxl.parse(mt940_file('statement-mt940')).first.transactions.last }
|
106
106
|
|
107
107
|
it { expect(subject.mt942?).to be_falsey }
|
@@ -167,4 +167,88 @@ describe Cmxl do
|
|
167
167
|
it { expect(statement.generation_date).to eql(Date.new(2019, 1, 9)) }
|
168
168
|
end
|
169
169
|
|
170
|
+
describe "header parsing" do
|
171
|
+
context "when strip_headers is enabled" do
|
172
|
+
around do |example|
|
173
|
+
existing_value = Cmxl.config[:strip_headers]
|
174
|
+
Cmxl.config[:strip_headers] = true
|
175
|
+
example.run
|
176
|
+
Cmxl.config[:strip_headers] = existing_value
|
177
|
+
end
|
178
|
+
|
179
|
+
it "removes any headers" do
|
180
|
+
data = <<~MT940.chomp
|
181
|
+
{1:D02AASDISLNETAXXXXXXXXXXXXX}
|
182
|
+
{2:E623XXXXXXXXAXXXN}
|
183
|
+
{4:
|
184
|
+
:20:MT940/78374
|
185
|
+
:25:xxxxxxxxxxxxxx
|
186
|
+
:28C:3/1
|
187
|
+
:60F:C160201INR0,00
|
188
|
+
:61:3622687806CR1368378,92NMSC37935531
|
189
|
+
:86:-TX TRN-REF NO.1156ADS5601187 EUR 13456/TSV
|
190
|
+
:62F:C141387INR11 27421,94
|
191
|
+
-}
|
192
|
+
MT940
|
193
|
+
|
194
|
+
result = Cmxl::Statement.new(data)
|
195
|
+
|
196
|
+
expect(result.fields.count).to eq(6)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "does nothing if there are no headers" do
|
200
|
+
data = <<~MT940.chomp
|
201
|
+
:20:MT940/78374
|
202
|
+
:25:xxxxxxxxxxxxxx
|
203
|
+
:28C:3/1
|
204
|
+
:60F:C160201INR0,00
|
205
|
+
:61:3622687806CR1368378,92NMSC37935531
|
206
|
+
:86:-TX TRN-REF NO.1156ADS5601187 EUR 13456/TSV
|
207
|
+
:62F:C141387INR11 27421,94
|
208
|
+
MT940
|
209
|
+
|
210
|
+
result = Cmxl::Statement.new(data)
|
211
|
+
|
212
|
+
expect(result.fields.count).to eq(6)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context "when strip_headers is disabled" do
|
217
|
+
it "raise an parsing error exception if headers are present" do
|
218
|
+
data = <<~MT940.chomp
|
219
|
+
{1:D02AASDISLNETAXXXXXXXXXXXXX}
|
220
|
+
{2:E623XXXXXXXXAXXXN}
|
221
|
+
{4:
|
222
|
+
:20:MT940/78374
|
223
|
+
:25:xxxxxxxxxxxxxx
|
224
|
+
:28C:3/1
|
225
|
+
:60F:C160201INR0,00
|
226
|
+
:61:3622687806CR1368378,92NMSC37935531
|
227
|
+
:86:-TX TRN-REF NO.1156ADS5601187 EUR 13456/TSV
|
228
|
+
:62F:C141387INR11 27421,94
|
229
|
+
-}
|
230
|
+
MT940
|
231
|
+
|
232
|
+
expect{
|
233
|
+
Cmxl::Statement.new(data)
|
234
|
+
}.to raise_error(Cmxl::Field::LineFormatError)
|
235
|
+
end
|
236
|
+
|
237
|
+
it "extracts the field" do
|
238
|
+
data = <<~MT940.chomp
|
239
|
+
:20:MT940/78374
|
240
|
+
:25:xxxxxxxxxxxxxx
|
241
|
+
:28C:3/1
|
242
|
+
:60F:C160201INR0,00
|
243
|
+
:61:3622687806CR1368378,92NMSC37935531
|
244
|
+
:86:-TX TRN-REF NO.1156ADS5601187 EUR 13456/TSV
|
245
|
+
:62F:C141387INR11 27421,94
|
246
|
+
MT940
|
247
|
+
|
248
|
+
result = Cmxl::Statement.new(data)
|
249
|
+
|
250
|
+
expect(result.fields.count).to eq(6)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
170
254
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cmxl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '2.
|
4
|
+
version: '2.1'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Bumann
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-01-
|
10
|
+
date: 2025-01-28 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: rchardet
|
@@ -163,9 +163,12 @@ files:
|
|
163
163
|
- spec/fixtures/lines/statement_supplementary_plain.txt
|
164
164
|
- spec/fixtures/lines/vmk_summary_credit.txt
|
165
165
|
- spec/fixtures/lines/vmk_summary_debit.txt
|
166
|
+
- spec/fixtures/mt940-abnamro.txt
|
166
167
|
- spec/fixtures/mt940-deutsche_bank.txt
|
168
|
+
- spec/fixtures/mt940-handelsbank.txt
|
167
169
|
- spec/fixtures/mt940-headers.txt
|
168
170
|
- spec/fixtures/mt940-iso8859-1.txt
|
171
|
+
- spec/fixtures/mt940-windows-line-breaks.txt
|
169
172
|
- spec/fixtures/mt940-with-colon-after-line-break.txt
|
170
173
|
- spec/fixtures/mt940-with-detailed-end-balance.txt
|
171
174
|
- spec/fixtures/mt940.txt
|
@@ -238,9 +241,12 @@ test_files:
|
|
238
241
|
- spec/fixtures/lines/statement_supplementary_plain.txt
|
239
242
|
- spec/fixtures/lines/vmk_summary_credit.txt
|
240
243
|
- spec/fixtures/lines/vmk_summary_debit.txt
|
244
|
+
- spec/fixtures/mt940-abnamro.txt
|
241
245
|
- spec/fixtures/mt940-deutsche_bank.txt
|
246
|
+
- spec/fixtures/mt940-handelsbank.txt
|
242
247
|
- spec/fixtures/mt940-headers.txt
|
243
248
|
- spec/fixtures/mt940-iso8859-1.txt
|
249
|
+
- spec/fixtures/mt940-windows-line-breaks.txt
|
244
250
|
- spec/fixtures/mt940-with-colon-after-line-break.txt
|
245
251
|
- spec/fixtures/mt940-with-detailed-end-balance.txt
|
246
252
|
- spec/fixtures/mt940.txt
|