cfonb 0.0.0 → 0.0.3

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,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