cfonb 0.0.0 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,470 @@
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: 'REFERENCE - OTHER REFERENCE',
41
+ purpose: 'PURPOSE',
42
+ rejection_code: '',
43
+ unavailability_code: '0',
44
+ value_date: Date.new(2019, 5, 16),
45
+ original_currency: nil,
46
+ original_amount: nil,
47
+ debtor: 'INTERNET SFR'
48
+ )
49
+
50
+ expect(statements[0].operations[1]).to have_attributes(
51
+ amount: -10.7,
52
+ currency: 'EUR',
53
+ date: Date.new(2019, 5, 16),
54
+ exoneration_code: '0',
55
+ interbank_code: 'B1',
56
+ internal_code: '9162',
57
+ label: 'VIR SEPA DEMONSTRATION',
58
+ number: 0,
59
+ reference: 'REFERENCE',
60
+ rejection_code: '',
61
+ unavailability_code: '0',
62
+ value_date: Date.new(2019, 5, 16),
63
+ original_currency: nil,
64
+ original_amount: nil,
65
+ debtor: 'ELEC ERDF'
66
+ )
67
+
68
+ expect(statements[0].operations[2]).to have_attributes(
69
+ amount: -7.9,
70
+ currency: 'EUR',
71
+ date: Date.new(2019, 5, 15),
72
+ exoneration_code: '1',
73
+ interbank_code: '62',
74
+ internal_code: '0117',
75
+ label: 'F COMMISSION D INTERVENTION',
76
+ number: 0,
77
+ reference: '',
78
+ rejection_code: '',
79
+ unavailability_code: '0',
80
+ value_date: Date.new(2019, 5, 15),
81
+ original_currency: nil,
82
+ original_amount: nil
83
+ )
84
+
85
+ expect(statements[1]).to have_attributes(
86
+ bank: '18706',
87
+ branch: '00000',
88
+ currency: 'EUR',
89
+ account: '00123456789',
90
+ from: Date.new(2019, 5, 16),
91
+ from_balance: -241.21,
92
+ to: Date.new(2019, 5, 17),
93
+ to_balance: -163.72
94
+ )
95
+
96
+ expect(statements[1].operations.size).to eq(3)
97
+
98
+ expect(statements[1].operations[0]).to have_attributes(
99
+ amount: BigDecimal('97.49', 4),
100
+ currency: 'EUR',
101
+ date: Date.new(2019, 5, 17),
102
+ exoneration_code: '',
103
+ interbank_code: 'A3',
104
+ internal_code: '0158',
105
+ label: "PRLV SEPA GROUPAMA CEN\nP051928612 22793301700040",
106
+ number: 0,
107
+ reference: '',
108
+ rejection_code: '',
109
+ unavailability_code: '0',
110
+ value_date: Date.new(2019, 5, 15),
111
+ original_currency: nil,
112
+ original_amount: nil
113
+ )
114
+
115
+ expect(statements[1].operations[1]).to have_attributes(
116
+ amount: -12.1,
117
+ currency: 'EUR',
118
+ date: Date.new(2019, 5, 15),
119
+ exoneration_code: '1',
120
+ interbank_code: '62',
121
+ internal_code: '0337',
122
+ label: 'F FRAIS PRLV IMP 97 49EUR',
123
+ number: 0,
124
+ reference: '',
125
+ rejection_code: '',
126
+ unavailability_code: '0',
127
+ value_date: Date.new(2019, 5, 15),
128
+ original_currency: nil,
129
+ original_amount: nil
130
+ )
131
+
132
+ expect(statements[1].operations[2]).to have_attributes(
133
+ amount: -7.9,
134
+ currency: 'EUR',
135
+ date: Date.new(2019, 5, 16),
136
+ exoneration_code: '1',
137
+ interbank_code: '62',
138
+ internal_code: '0117',
139
+ label: 'F COMMISSION D INTERVENTION',
140
+ number: 0,
141
+ reference: '',
142
+ rejection_code: '',
143
+ unavailability_code: '0',
144
+ value_date: Date.new(2019, 5, 16),
145
+ original_currency: nil,
146
+ original_amount: nil
147
+ )
148
+ end
149
+ end
150
+
151
+ context 'with an operation out of a statement' do
152
+ let(:input) { File.read('spec/files/operation_out_of_statement.txt') }
153
+
154
+ it 'raises UnstartedStatementError' do
155
+ expect do
156
+ statements
157
+ end.to raise_error(CFONB::UnstartedStatementError)
158
+ end
159
+ end
160
+
161
+ context 'with an operation detail without an operation' do
162
+ let(:input) { File.read('spec/files/operation_detail_without_operation.txt') }
163
+
164
+ it 'raises UnstartedOperationError' do
165
+ expect do
166
+ statements
167
+ end.to raise_error(CFONB::UnstartedOperationError)
168
+ end
169
+ end
170
+
171
+ context 'with an end of statement without its beginning' do
172
+ let(:input) { File.read('spec/files/end_of_statement_without_beginning.txt') }
173
+
174
+ it 'raises UnstartedStatementError' do
175
+ expect do
176
+ statements
177
+ end.to raise_error(CFONB::UnstartedStatementError)
178
+ end
179
+ end
180
+
181
+ context 'with a new statement starting without the previous being finished' do
182
+ let(:input) { File.read('spec/files/new_statement_without_previous_ended.txt') }
183
+
184
+ it 'raises UnfinishedStatementError' do
185
+ expect do
186
+ statements
187
+ end.to raise_error(CFONB::UnfinishedStatementError)
188
+ end
189
+ end
190
+
191
+ context 'when parser error' do
192
+ let(:input) { File.read('spec/files/invalid_date.txt') }
193
+
194
+ it 'raises CFONB::ParserError' do
195
+ expect { statements }.to raise_error(CFONB::ParserError)
196
+ end
197
+ end
198
+
199
+ context 'with an optimistic parse' do
200
+ subject(:statements) { described_class.new(input).parse(optimistic: true) }
201
+
202
+ context 'with a valid input' do
203
+ it 'parses correctly' do
204
+ expect(statements).to contain_exactly(
205
+ an_instance_of(CFONB::Statement),
206
+ an_instance_of(CFONB::Statement)
207
+ )
208
+
209
+ expect(statements[0]).to have_attributes(
210
+ bank: '15589',
211
+ branch: '00000',
212
+ currency: 'EUR',
213
+ account: '98765432100',
214
+ from: Date.new(2019, 5, 15),
215
+ from_balance: -190.4,
216
+ to: Date.new(2019, 5, 16),
217
+ to_balance: -241.21
218
+ )
219
+
220
+ expect(statements[0].operations.size).to eq(3)
221
+
222
+ expect(statements[0].operations[0]).to have_attributes(
223
+ amount: -32.21,
224
+ currency: 'EUR',
225
+ date: Date.new(2019, 5, 16),
226
+ exoneration_code: '0',
227
+ interbank_code: 'B1',
228
+ internal_code: '9162',
229
+ label: "PRLV SEPA TEST CABINET\nMENSUEAUHTR13133",
230
+ number: 0,
231
+ reference: 'REFERENCE - OTHER REFERENCE',
232
+ rejection_code: '',
233
+ unavailability_code: '0',
234
+ value_date: Date.new(2019, 5, 16),
235
+ original_currency: nil,
236
+ original_amount: nil,
237
+ debtor: 'INTERNET SFR'
238
+ )
239
+
240
+ expect(statements[0].operations[1]).to have_attributes(
241
+ amount: -10.7,
242
+ currency: 'EUR',
243
+ date: Date.new(2019, 5, 16),
244
+ exoneration_code: '0',
245
+ interbank_code: 'B1',
246
+ internal_code: '9162',
247
+ label: 'VIR SEPA DEMONSTRATION',
248
+ number: 0,
249
+ reference: 'REFERENCE',
250
+ rejection_code: '',
251
+ unavailability_code: '0',
252
+ value_date: Date.new(2019, 5, 16),
253
+ original_currency: nil,
254
+ original_amount: nil,
255
+ debtor: 'ELEC ERDF'
256
+ )
257
+
258
+ expect(statements[0].operations[2]).to have_attributes(
259
+ amount: -7.9,
260
+ currency: 'EUR',
261
+ date: Date.new(2019, 5, 15),
262
+ exoneration_code: '1',
263
+ interbank_code: '62',
264
+ internal_code: '0117',
265
+ label: 'F COMMISSION D INTERVENTION',
266
+ number: 0,
267
+ reference: '',
268
+ rejection_code: '',
269
+ unavailability_code: '0',
270
+ value_date: Date.new(2019, 5, 15),
271
+ original_currency: nil,
272
+ original_amount: nil
273
+ )
274
+
275
+ expect(statements[1]).to have_attributes(
276
+ bank: '18706',
277
+ branch: '00000',
278
+ currency: 'EUR',
279
+ account: '00123456789',
280
+ from: Date.new(2019, 5, 16),
281
+ from_balance: -241.21,
282
+ to: Date.new(2019, 5, 17),
283
+ to_balance: -163.72
284
+ )
285
+
286
+ expect(statements[1].operations.size).to eq(3)
287
+
288
+ expect(statements[1].operations[0]).to have_attributes(
289
+ amount: BigDecimal('97.49', 4),
290
+ currency: 'EUR',
291
+ date: Date.new(2019, 5, 17),
292
+ exoneration_code: '',
293
+ interbank_code: 'A3',
294
+ internal_code: '0158',
295
+ label: "PRLV SEPA GROUPAMA CEN\nP051928612 22793301700040",
296
+ number: 0,
297
+ reference: '',
298
+ rejection_code: '',
299
+ unavailability_code: '0',
300
+ value_date: Date.new(2019, 5, 15),
301
+ original_currency: nil,
302
+ original_amount: nil
303
+ )
304
+
305
+ expect(statements[1].operations[1]).to have_attributes(
306
+ amount: -12.1,
307
+ currency: 'EUR',
308
+ date: Date.new(2019, 5, 15),
309
+ exoneration_code: '1',
310
+ interbank_code: '62',
311
+ internal_code: '0337',
312
+ label: 'F FRAIS PRLV IMP 97 49EUR',
313
+ number: 0,
314
+ reference: '',
315
+ rejection_code: '',
316
+ unavailability_code: '0',
317
+ value_date: Date.new(2019, 5, 15),
318
+ original_currency: nil,
319
+ original_amount: nil
320
+ )
321
+
322
+ expect(statements[1].operations[2]).to have_attributes(
323
+ amount: -7.9,
324
+ currency: 'EUR',
325
+ date: Date.new(2019, 5, 16),
326
+ exoneration_code: '1',
327
+ interbank_code: '62',
328
+ internal_code: '0117',
329
+ label: 'F COMMISSION D INTERVENTION',
330
+ number: 0,
331
+ reference: '',
332
+ rejection_code: '',
333
+ unavailability_code: '0',
334
+ value_date: Date.new(2019, 5, 16),
335
+ original_currency: nil,
336
+ original_amount: nil
337
+ )
338
+ end
339
+ end
340
+
341
+ context 'with an operation out of a statement' do
342
+ let(:input) { File.read('spec/files/operation_out_of_statement.txt') }
343
+
344
+ it 'ignores the operation' do
345
+ expect(statements.size).to eq(1)
346
+ expect(statements[0].operations.size).to eq(1)
347
+ expect(statements[0].operations[0]).to have_attributes(
348
+ amount: -10.7,
349
+ currency: 'EUR',
350
+ date: Date.new(2019, 5, 16),
351
+ exoneration_code: '0',
352
+ interbank_code: 'B1',
353
+ internal_code: '9162',
354
+ label: 'VIR SEPA DEMONSTRATION',
355
+ number: 0,
356
+ reference: '',
357
+ rejection_code: '',
358
+ unavailability_code: '0',
359
+ value_date: Date.new(2019, 5, 16),
360
+ original_currency: nil,
361
+ original_amount: nil,
362
+ debtor: 'ELEC ERDF'
363
+ )
364
+ end
365
+ end
366
+
367
+ context 'with an operation detail without an operation' do
368
+ let(:input) { File.read('spec/files/operation_detail_without_operation.txt') }
369
+
370
+ it 'ignores the operation detail' do
371
+ expect(statements.size).to eq(1)
372
+ expect(statements[0].operations.size).to eq(1)
373
+ expect(statements[0].operations[0]).to have_attributes(
374
+ amount: -10.7,
375
+ currency: 'EUR',
376
+ date: Date.new(2019, 5, 16),
377
+ exoneration_code: '0',
378
+ interbank_code: 'B1',
379
+ internal_code: '9162',
380
+ label: 'VIR SEPA DEMONSTRATION',
381
+ number: 0,
382
+ reference: '',
383
+ rejection_code: '',
384
+ unavailability_code: '0',
385
+ value_date: Date.new(2019, 5, 16),
386
+ original_currency: nil,
387
+ original_amount: nil,
388
+ debtor: 'ELEC ERDF'
389
+ )
390
+ end
391
+ end
392
+
393
+ context 'with an end of statement without its beginning' do
394
+ let(:input) { File.read('spec/files/end_of_statement_without_beginning.txt') }
395
+
396
+ it 'ignores the end of statement' do
397
+ expect(statements.size).to eq(1)
398
+ expect(statements[0].operations.size).to eq(1)
399
+ expect(statements[0].operations[0]).to have_attributes(
400
+ amount: -10.7,
401
+ currency: 'EUR',
402
+ date: Date.new(2019, 5, 16),
403
+ exoneration_code: '0',
404
+ interbank_code: 'B1',
405
+ internal_code: '9162',
406
+ label: 'VIR SEPA DEMONSTRATION',
407
+ number: 0,
408
+ reference: '',
409
+ rejection_code: '',
410
+ unavailability_code: '0',
411
+ value_date: Date.new(2019, 5, 16),
412
+ original_currency: nil,
413
+ original_amount: nil,
414
+ debtor: 'ELEC ERDF'
415
+ )
416
+ end
417
+ end
418
+
419
+ context 'with a new statement starting without the previous being finished' do
420
+ let(:input) { File.read('spec/files/new_statement_without_previous_ended.txt') }
421
+
422
+ it 'ignores the new statement' do
423
+ expect(statements.size).to eq(1)
424
+ expect(statements[0].operations.size).to eq(2)
425
+ expect(statements[0].operations[0]).to have_attributes(
426
+ amount: -10.7,
427
+ currency: 'EUR',
428
+ date: Date.new(2019, 5, 16),
429
+ exoneration_code: '0',
430
+ interbank_code: 'B1',
431
+ internal_code: '9162',
432
+ label: 'VIR SEPA DEMONSTRATION',
433
+ number: 0,
434
+ reference: '',
435
+ rejection_code: '',
436
+ unavailability_code: '0',
437
+ value_date: Date.new(2019, 5, 16),
438
+ original_currency: nil,
439
+ original_amount: nil,
440
+ debtor: 'ELEC ERDF'
441
+ )
442
+ expect(statements[0].operations[1]).to have_attributes(
443
+ amount: -7.9,
444
+ currency: 'EUR',
445
+ date: Date.new(2019, 5, 16),
446
+ exoneration_code: '1',
447
+ interbank_code: '62',
448
+ internal_code: '0117',
449
+ label: 'F COMMISSION D INTERVENTION',
450
+ number: 0,
451
+ reference: '',
452
+ rejection_code: '',
453
+ unavailability_code: '0',
454
+ value_date: Date.new(2019, 5, 16),
455
+ original_currency: nil,
456
+ original_amount: nil
457
+ )
458
+ end
459
+ end
460
+
461
+ context 'when parser error' do
462
+ let(:input) { File.read('spec/files/invalid_date.txt') }
463
+
464
+ it 'returns empty statements' do
465
+ expect(statements.size).to eq(0)
466
+ end
467
+ end
468
+ end
469
+ end
470
+ 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.3
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-26 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