cfonb 0.0.0 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,469 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cfonb'
4
+
5
+ describe CFONB::Parser do
6
+ describe '.parse' do
7
+ subject(:statements) { described_class.new(input).parse }
8
+
9
+ let(:input) { File.read('spec/files/example.txt') }
10
+
11
+ context 'with a valid input' do
12
+ it 'parses correctly' do
13
+ expect(statements).to contain_exactly(
14
+ an_instance_of(CFONB::Statement),
15
+ an_instance_of(CFONB::Statement)
16
+ )
17
+
18
+ expect(statements[0]).to have_attributes(
19
+ bank: '15589',
20
+ branch: '00000',
21
+ currency: 'EUR',
22
+ account: '98765432100',
23
+ from: Date.new(2019, 5, 15),
24
+ from_balance: -190.4,
25
+ to: Date.new(2019, 5, 16),
26
+ to_balance: -241.21
27
+ )
28
+
29
+ expect(statements[0].operations.size).to eq(3)
30
+
31
+ expect(statements[0].operations[0]).to have_attributes(
32
+ amount: -32.21,
33
+ currency: 'EUR',
34
+ date: Date.new(2019, 5, 16),
35
+ exoneration_code: '0',
36
+ interbank_code: 'B1',
37
+ internal_code: '9162',
38
+ label: "PRLV SEPA TEST CABINET\nMENSUEAUHTR13133",
39
+ number: 0,
40
+ reference: '',
41
+ rejection_code: '',
42
+ unavailability_code: '0',
43
+ value_date: Date.new(2019, 5, 16),
44
+ original_currency: nil,
45
+ original_amount: nil,
46
+ debtor: 'INTERNET SFR'
47
+ )
48
+
49
+ expect(statements[0].operations[1]).to have_attributes(
50
+ amount: -10.7,
51
+ currency: 'EUR',
52
+ date: Date.new(2019, 5, 16),
53
+ exoneration_code: '0',
54
+ interbank_code: 'B1',
55
+ internal_code: '9162',
56
+ label: 'VIR SEPA DEMONSTRATION',
57
+ number: 0,
58
+ reference: '',
59
+ rejection_code: '',
60
+ unavailability_code: '0',
61
+ value_date: Date.new(2019, 5, 16),
62
+ original_currency: nil,
63
+ original_amount: nil,
64
+ debtor: 'ELEC ERDF'
65
+ )
66
+
67
+ expect(statements[0].operations[2]).to have_attributes(
68
+ amount: -7.9,
69
+ currency: 'EUR',
70
+ date: Date.new(2019, 5, 15),
71
+ exoneration_code: '1',
72
+ interbank_code: '62',
73
+ internal_code: '0117',
74
+ label: 'F COMMISSION D INTERVENTION',
75
+ number: 0,
76
+ reference: '',
77
+ rejection_code: '',
78
+ unavailability_code: '0',
79
+ value_date: Date.new(2019, 5, 15),
80
+ original_currency: nil,
81
+ original_amount: nil
82
+ )
83
+
84
+ expect(statements[1]).to have_attributes(
85
+ bank: '18706',
86
+ branch: '00000',
87
+ currency: 'EUR',
88
+ account: '00123456789',
89
+ from: Date.new(2019, 5, 16),
90
+ from_balance: -241.21,
91
+ to: Date.new(2019, 5, 17),
92
+ to_balance: -163.72
93
+ )
94
+
95
+ expect(statements[1].operations.size).to eq(3)
96
+
97
+ expect(statements[1].operations[0]).to have_attributes(
98
+ amount: BigDecimal('97.49', 4),
99
+ currency: 'EUR',
100
+ date: Date.new(2019, 5, 17),
101
+ exoneration_code: '',
102
+ interbank_code: 'A3',
103
+ internal_code: '0158',
104
+ label: "PRLV SEPA GROUPAMA CEN\nP051928612 22793301700040",
105
+ number: 0,
106
+ reference: '',
107
+ rejection_code: '',
108
+ unavailability_code: '0',
109
+ value_date: Date.new(2019, 5, 15),
110
+ original_currency: nil,
111
+ original_amount: nil
112
+ )
113
+
114
+ expect(statements[1].operations[1]).to have_attributes(
115
+ amount: -12.1,
116
+ currency: 'EUR',
117
+ date: Date.new(2019, 5, 15),
118
+ exoneration_code: '1',
119
+ interbank_code: '62',
120
+ internal_code: '0337',
121
+ label: 'F FRAIS PRLV IMP 97 49EUR',
122
+ number: 0,
123
+ reference: '',
124
+ rejection_code: '',
125
+ unavailability_code: '0',
126
+ value_date: Date.new(2019, 5, 15),
127
+ original_currency: nil,
128
+ original_amount: nil
129
+ )
130
+
131
+ expect(statements[1].operations[2]).to have_attributes(
132
+ amount: -7.9,
133
+ currency: 'EUR',
134
+ date: Date.new(2019, 5, 16),
135
+ exoneration_code: '1',
136
+ interbank_code: '62',
137
+ internal_code: '0117',
138
+ label: 'F COMMISSION D INTERVENTION',
139
+ number: 0,
140
+ reference: '',
141
+ rejection_code: '',
142
+ unavailability_code: '0',
143
+ value_date: Date.new(2019, 5, 16),
144
+ original_currency: nil,
145
+ original_amount: nil
146
+ )
147
+ end
148
+ end
149
+
150
+ context 'with an operation out of a statement' do
151
+ let(:input) { File.read('spec/files/operation_out_of_statement.txt') }
152
+
153
+ it 'raises UnstartedStatementError' do
154
+ expect do
155
+ statements
156
+ end.to raise_error(CFONB::UnstartedStatementError)
157
+ end
158
+ end
159
+
160
+ context 'with an operation detail without an operation' do
161
+ let(:input) { File.read('spec/files/operation_detail_without_operation.txt') }
162
+
163
+ it 'raises UnstartedOperationError' do
164
+ expect do
165
+ statements
166
+ end.to raise_error(CFONB::UnstartedOperationError)
167
+ end
168
+ end
169
+
170
+ context 'with an end of statement without its beginning' do
171
+ let(:input) { File.read('spec/files/end_of_statement_without_beginning.txt') }
172
+
173
+ it 'raises UnstartedStatementError' do
174
+ expect do
175
+ statements
176
+ end.to raise_error(CFONB::UnstartedStatementError)
177
+ end
178
+ end
179
+
180
+ context 'with a new statement starting without the previous being finished' do
181
+ let(:input) { File.read('spec/files/new_statement_without_previous_ended.txt') }
182
+
183
+ it 'raises UnfinishedStatementError' do
184
+ expect do
185
+ statements
186
+ end.to raise_error(CFONB::UnfinishedStatementError)
187
+ end
188
+ end
189
+
190
+ context 'when parser error' do
191
+ let(:input) { File.read('spec/files/invalid_date.txt') }
192
+
193
+ it 'raises CFONB::ParserError' do
194
+ expect { statements }.to raise_error(CFONB::ParserError)
195
+ end
196
+ end
197
+
198
+ context 'with an optimistic parse' do
199
+ subject(:statements) { described_class.new(input).parse(optimistic: true) }
200
+
201
+ context 'with a valid input' do
202
+ it 'parses correctly' do
203
+ expect(statements).to contain_exactly(
204
+ an_instance_of(CFONB::Statement),
205
+ an_instance_of(CFONB::Statement)
206
+ )
207
+
208
+ expect(statements[0]).to have_attributes(
209
+ bank: '15589',
210
+ branch: '00000',
211
+ currency: 'EUR',
212
+ account: '98765432100',
213
+ from: Date.new(2019, 5, 15),
214
+ from_balance: -190.4,
215
+ to: Date.new(2019, 5, 16),
216
+ to_balance: -241.21
217
+ )
218
+
219
+ expect(statements[0].operations.size).to eq(3)
220
+
221
+ expect(statements[0].operations[0]).to have_attributes(
222
+ amount: -32.21,
223
+ currency: 'EUR',
224
+ date: Date.new(2019, 5, 16),
225
+ exoneration_code: '0',
226
+ interbank_code: 'B1',
227
+ internal_code: '9162',
228
+ label: "PRLV SEPA TEST CABINET\nMENSUEAUHTR13133",
229
+ number: 0,
230
+ reference: '',
231
+ rejection_code: '',
232
+ unavailability_code: '0',
233
+ value_date: Date.new(2019, 5, 16),
234
+ original_currency: nil,
235
+ original_amount: nil,
236
+ debtor: 'INTERNET SFR'
237
+ )
238
+
239
+ expect(statements[0].operations[1]).to have_attributes(
240
+ amount: -10.7,
241
+ currency: 'EUR',
242
+ date: Date.new(2019, 5, 16),
243
+ exoneration_code: '0',
244
+ interbank_code: 'B1',
245
+ internal_code: '9162',
246
+ label: 'VIR SEPA DEMONSTRATION',
247
+ number: 0,
248
+ reference: '',
249
+ rejection_code: '',
250
+ unavailability_code: '0',
251
+ value_date: Date.new(2019, 5, 16),
252
+ original_currency: nil,
253
+ original_amount: nil,
254
+ debtor: 'ELEC ERDF'
255
+ )
256
+
257
+ expect(statements[0].operations[2]).to have_attributes(
258
+ amount: -7.9,
259
+ currency: 'EUR',
260
+ date: Date.new(2019, 5, 15),
261
+ exoneration_code: '1',
262
+ interbank_code: '62',
263
+ internal_code: '0117',
264
+ label: 'F COMMISSION D INTERVENTION',
265
+ number: 0,
266
+ reference: '',
267
+ rejection_code: '',
268
+ unavailability_code: '0',
269
+ value_date: Date.new(2019, 5, 15),
270
+ original_currency: nil,
271
+ original_amount: nil
272
+ )
273
+
274
+ expect(statements[1]).to have_attributes(
275
+ bank: '18706',
276
+ branch: '00000',
277
+ currency: 'EUR',
278
+ account: '00123456789',
279
+ from: Date.new(2019, 5, 16),
280
+ from_balance: -241.21,
281
+ to: Date.new(2019, 5, 17),
282
+ to_balance: -163.72
283
+ )
284
+
285
+ expect(statements[1].operations.size).to eq(3)
286
+
287
+ expect(statements[1].operations[0]).to have_attributes(
288
+ amount: BigDecimal('97.49', 4),
289
+ currency: 'EUR',
290
+ date: Date.new(2019, 5, 17),
291
+ exoneration_code: '',
292
+ interbank_code: 'A3',
293
+ internal_code: '0158',
294
+ label: "PRLV SEPA GROUPAMA CEN\nP051928612 22793301700040",
295
+ number: 0,
296
+ reference: '',
297
+ rejection_code: '',
298
+ unavailability_code: '0',
299
+ value_date: Date.new(2019, 5, 15),
300
+ original_currency: nil,
301
+ original_amount: nil
302
+ )
303
+
304
+ expect(statements[1].operations[1]).to have_attributes(
305
+ amount: -12.1,
306
+ currency: 'EUR',
307
+ date: Date.new(2019, 5, 15),
308
+ exoneration_code: '1',
309
+ interbank_code: '62',
310
+ internal_code: '0337',
311
+ label: 'F FRAIS PRLV IMP 97 49EUR',
312
+ number: 0,
313
+ reference: '',
314
+ rejection_code: '',
315
+ unavailability_code: '0',
316
+ value_date: Date.new(2019, 5, 15),
317
+ original_currency: nil,
318
+ original_amount: nil
319
+ )
320
+
321
+ expect(statements[1].operations[2]).to have_attributes(
322
+ amount: -7.9,
323
+ currency: 'EUR',
324
+ date: Date.new(2019, 5, 16),
325
+ exoneration_code: '1',
326
+ interbank_code: '62',
327
+ internal_code: '0117',
328
+ label: 'F COMMISSION D INTERVENTION',
329
+ number: 0,
330
+ reference: '',
331
+ rejection_code: '',
332
+ unavailability_code: '0',
333
+ value_date: Date.new(2019, 5, 16),
334
+ original_currency: nil,
335
+ original_amount: nil
336
+ )
337
+ end
338
+ end
339
+
340
+ context 'with an operation out of a statement' do
341
+ let(:input) { File.read('spec/files/operation_out_of_statement.txt') }
342
+
343
+ it 'ignores the operation' do
344
+ expect(statements.size).to eq(1)
345
+ expect(statements[0].operations.size).to eq(1)
346
+ expect(statements[0].operations[0]).to have_attributes(
347
+ amount: -10.7,
348
+ currency: 'EUR',
349
+ date: Date.new(2019, 5, 16),
350
+ exoneration_code: '0',
351
+ interbank_code: 'B1',
352
+ internal_code: '9162',
353
+ label: 'VIR SEPA DEMONSTRATION',
354
+ number: 0,
355
+ reference: '',
356
+ rejection_code: '',
357
+ unavailability_code: '0',
358
+ value_date: Date.new(2019, 5, 16),
359
+ original_currency: nil,
360
+ original_amount: nil,
361
+ debtor: 'ELEC ERDF'
362
+ )
363
+ end
364
+ end
365
+
366
+ context 'with an operation detail without an operation' do
367
+ let(:input) { File.read('spec/files/operation_detail_without_operation.txt') }
368
+
369
+ it 'ignores the operation detail' do
370
+ expect(statements.size).to eq(1)
371
+ expect(statements[0].operations.size).to eq(1)
372
+ expect(statements[0].operations[0]).to have_attributes(
373
+ amount: -10.7,
374
+ currency: 'EUR',
375
+ date: Date.new(2019, 5, 16),
376
+ exoneration_code: '0',
377
+ interbank_code: 'B1',
378
+ internal_code: '9162',
379
+ label: 'VIR SEPA DEMONSTRATION',
380
+ number: 0,
381
+ reference: '',
382
+ rejection_code: '',
383
+ unavailability_code: '0',
384
+ value_date: Date.new(2019, 5, 16),
385
+ original_currency: nil,
386
+ original_amount: nil,
387
+ debtor: 'ELEC ERDF'
388
+ )
389
+ end
390
+ end
391
+
392
+ context 'with an end of statement without its beginning' do
393
+ let(:input) { File.read('spec/files/end_of_statement_without_beginning.txt') }
394
+
395
+ it 'ignores the end of statement' do
396
+ expect(statements.size).to eq(1)
397
+ expect(statements[0].operations.size).to eq(1)
398
+ expect(statements[0].operations[0]).to have_attributes(
399
+ amount: -10.7,
400
+ currency: 'EUR',
401
+ date: Date.new(2019, 5, 16),
402
+ exoneration_code: '0',
403
+ interbank_code: 'B1',
404
+ internal_code: '9162',
405
+ label: 'VIR SEPA DEMONSTRATION',
406
+ number: 0,
407
+ reference: '',
408
+ rejection_code: '',
409
+ unavailability_code: '0',
410
+ value_date: Date.new(2019, 5, 16),
411
+ original_currency: nil,
412
+ original_amount: nil,
413
+ debtor: 'ELEC ERDF'
414
+ )
415
+ end
416
+ end
417
+
418
+ context 'with a new statement starting without the previous being finished' do
419
+ let(:input) { File.read('spec/files/new_statement_without_previous_ended.txt') }
420
+
421
+ it 'ignores the new statement' do
422
+ expect(statements.size).to eq(1)
423
+ expect(statements[0].operations.size).to eq(2)
424
+ expect(statements[0].operations[0]).to have_attributes(
425
+ amount: -10.7,
426
+ currency: 'EUR',
427
+ date: Date.new(2019, 5, 16),
428
+ exoneration_code: '0',
429
+ interbank_code: 'B1',
430
+ internal_code: '9162',
431
+ label: 'VIR SEPA DEMONSTRATION',
432
+ number: 0,
433
+ reference: '',
434
+ rejection_code: '',
435
+ unavailability_code: '0',
436
+ value_date: Date.new(2019, 5, 16),
437
+ original_currency: nil,
438
+ original_amount: nil,
439
+ debtor: 'ELEC ERDF'
440
+ )
441
+ expect(statements[0].operations[1]).to have_attributes(
442
+ amount: -7.9,
443
+ currency: 'EUR',
444
+ date: Date.new(2019, 5, 16),
445
+ exoneration_code: '1',
446
+ interbank_code: '62',
447
+ internal_code: '0117',
448
+ label: 'F COMMISSION D INTERVENTION',
449
+ number: 0,
450
+ reference: '',
451
+ rejection_code: '',
452
+ unavailability_code: '0',
453
+ value_date: Date.new(2019, 5, 16),
454
+ original_currency: nil,
455
+ original_amount: nil
456
+ )
457
+ end
458
+ end
459
+
460
+ context 'when parser error' do
461
+ let(:input) { File.read('spec/files/invalid_date.txt') }
462
+
463
+ it 'returns empty statements' do
464
+ expect(statements.size).to eq(0)
465
+ end
466
+ end
467
+ end
468
+ end
469
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cfonb'
4
+
5
+ describe CFONB::Statement do
6
+ subject(:statement) do
7
+ described_class.new(begin_line)
8
+ .tap { _1.operations << operation }
9
+ .tap { _1.merge_new_balance(end_line) }
10
+ end
11
+
12
+ let(:operation) do
13
+ CFONB::Operation
14
+ .new(operation_line)
15
+ .tap { _1.merge_detail(detail_line) }
16
+ end
17
+
18
+ let(:begin_line) do
19
+ CFONB::LineParser.parse(
20
+ '0115589 00000EUR2 98765432100 150519 0000000001904}150519160519 '
21
+ )
22
+ end
23
+ let(:operation_line) do
24
+ CFONB::LineParser.parse(
25
+ '0415589916200000EUR2 98765432100B1160519 160519PRLV SEPA TEST CABINET 0000000000000000000322J '
26
+ )
27
+ end
28
+ let(:detail_line) do
29
+ CFONB::LineParser.parse(
30
+ '0515589916200000EUR2 98765432100B1160519 LIBMENSUEAUHTR13133 '
31
+ )
32
+ end
33
+ let(:end_line) do
34
+ CFONB::LineParser.parse(
35
+ '0715489 00000EUR2 98765432100 160519 0000000002412J '
36
+ )
37
+ end
38
+
39
+ describe '#raw' do
40
+ it 'joins all the statement raws' do
41
+ expect(statement.raw).to eq(<<~TXT.chomp)
42
+ 0115589 00000EUR2 98765432100 150519 0000000001904}150519160519#{' '}
43
+ 0415589916200000EUR2 98765432100B1160519 160519PRLV SEPA TEST CABINET 0000000000000000000322J#{' '}
44
+ 0515589916200000EUR2 98765432100B1160519 LIBMENSUEAUHTR13133#{' '}
45
+ 0715489 00000EUR2 98765432100 160519 0000000002412J#{' '}
46
+ TXT
47
+ end
48
+ end
49
+
50
+ describe '#rib' do
51
+ it 'returns the correct rib' do
52
+ expect(statement.rib).to eq('15589000009876543210088')
53
+ end
54
+ end
55
+
56
+ describe '#iban' do
57
+ it 'returns the correct iban' do
58
+ expect(statement.iban).to eq('FR7615589000009876543210088')
59
+ end
60
+ end
61
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cfonb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johan Le Bray
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-09-08 00:00:00.000000000 Z
12
+ date: 2023-09-25 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: An easy to use CFONB format parser
15
15
  email: ''
@@ -18,7 +18,36 @@ extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
20
  - lib/cfonb.rb
21
- homepage: https://rubygems.org/gems/cfonb
21
+ - lib/cfonb/error.rb
22
+ - lib/cfonb/line_parser.rb
23
+ - lib/cfonb/line_parser/base.rb
24
+ - lib/cfonb/line_parser/new_balance.rb
25
+ - lib/cfonb/line_parser/operation.rb
26
+ - lib/cfonb/line_parser/operation_detail.rb
27
+ - lib/cfonb/line_parser/previous_balance.rb
28
+ - lib/cfonb/operation.rb
29
+ - lib/cfonb/operation_detail.rb
30
+ - lib/cfonb/operation_detail/fee.rb
31
+ - lib/cfonb/operation_detail/lc2.rb
32
+ - lib/cfonb/operation_detail/lcc.rb
33
+ - lib/cfonb/operation_detail/lcs.rb
34
+ - lib/cfonb/operation_detail/lib.rb
35
+ - lib/cfonb/operation_detail/mmo.rb
36
+ - lib/cfonb/operation_detail/nbe.rb
37
+ - lib/cfonb/operation_detail/npy.rb
38
+ - lib/cfonb/operation_detail/rcn.rb
39
+ - lib/cfonb/operation_detail/ref.rb
40
+ - lib/cfonb/parser.rb
41
+ - lib/cfonb/refinements/strings.rb
42
+ - lib/cfonb/statement.rb
43
+ - spec/cfonb/line_parser/new_balance_spec.rb
44
+ - spec/cfonb/line_parser/operation_detail_spec.rb
45
+ - spec/cfonb/line_parser/operation_spec.rb
46
+ - spec/cfonb/line_parser/previous_balance_spec.rb
47
+ - spec/cfonb/operation_spec.rb
48
+ - spec/cfonb/parser_spec.rb
49
+ - spec/cfonb/statement_spec.rb
50
+ homepage: https://github.com/pennylane-hq/cfonb
22
51
  licenses:
23
52
  - MIT
24
53
  metadata: {}
@@ -37,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
37
66
  - !ruby/object:Gem::Version
38
67
  version: '0'
39
68
  requirements: []
40
- rubygems_version: 3.3.26
69
+ rubygems_version: 3.4.10
41
70
  signing_key:
42
71
  specification_version: 4
43
72
  summary: CFONB parser