cfonb 0.0.0 → 0.0.2

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.
@@ -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