ibandit 0.1.1 → 0.2.0

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.
File without changes
File without changes
File without changes
data/lib/ibandit.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'ibandit/version'
2
2
  require 'ibandit/errors'
3
3
  require 'ibandit/iban'
4
+ require 'ibandit/german_details_converter'
4
5
  require 'ibandit/iban_builder'
5
6
  require 'ibandit/check_digit'
6
7
 
@@ -2,4 +2,5 @@ module Ibandit
2
2
  class BicNotFoundError < StandardError; end
3
3
  class InvalidCharacterError < StandardError; end
4
4
  class UnsupportedCountryError < StandardError; end
5
+ class UnsupportedAccountDetails < StandardError; end
5
6
  end
@@ -0,0 +1,1277 @@
1
+ # German bank details don't map directly to IBANs in the same way as in other
2
+ # countries - each bank has idiosyncracies for translating its cusomers' bank
3
+ # details. These idiosyncracies are described in a document from the Bundesbank:
4
+ # http://www.bundesbank.de/Navigation/DE/Aufgaben/Unbarer_Zahlungsverkehr/IBAN_Regeln/iban_regeln.html
5
+
6
+ module Ibandit
7
+ module GermanDetailsConverter
8
+ def self.rules
9
+ @rules ||= YAML.load_file(
10
+ File.expand_path('../../../data/german_iban_rules.yml', __FILE__)
11
+ )
12
+ end
13
+
14
+ def self.convert(opts)
15
+ # Fetch the relevant rule number. Default to '000000'
16
+ rule_num = rules.fetch(opts[:bank_code], {}).fetch(:iban_rule, '000000')
17
+
18
+ # Convert the bank details using the relevant rule
19
+ updated_bank_details = const_get("Rule#{rule_num}").new(
20
+ opts[:bank_code],
21
+ opts[:account_number]
22
+ ).converted_details
23
+
24
+ opts.merge(updated_bank_details)
25
+ end
26
+
27
+ ##############
28
+ # IBAN Rules #
29
+ ##############
30
+
31
+ class BaseRule
32
+ def initialize(bank_code, account_number)
33
+ @bank_code = bank_code
34
+ @account_number = account_number
35
+ end
36
+
37
+ def converted_details
38
+ raise NotImplementedError, 'Concrete RuleXXXXXX classes should ' \
39
+ 'define a converted_details function'
40
+ end
41
+ end
42
+
43
+ module PseudoAccountNumberBehaviour
44
+ def self.included(o)
45
+ o.extend(ClassMethods)
46
+ end
47
+
48
+ module ClassMethods
49
+ attr_reader :pseudo_account_number_mapping
50
+ end
51
+
52
+ def converted_details
53
+ updated_account_number =
54
+ pseudo_account_number_mapping.fetch(
55
+ @account_number.rjust(10, '0'),
56
+ @account_number
57
+ )
58
+
59
+ { bank_code: @bank_code, account_number: updated_account_number }
60
+ end
61
+
62
+ def pseudo_account_number_mapping
63
+ self.class.pseudo_account_number_mapping.freeze
64
+ end
65
+ end
66
+
67
+ class Rule000000 < BaseRule
68
+ def converted_details
69
+ { bank_code: @bank_code, account_number: @account_number }
70
+ end
71
+ end
72
+
73
+ class Rule000100 < BaseRule
74
+ def converted_details
75
+ msg = "Bank code #{@bank_code} is not used for payment transactions"
76
+ raise UnsupportedAccountDetails, msg
77
+ end
78
+ end
79
+
80
+ class Rule000200 < BaseRule
81
+ def converted_details
82
+ if @account_number.rjust(10, '0')[7] == '6' ||
83
+ @account_number.rjust(10, '0').slice(7, 2) == '86'
84
+ msg = 'Account does not support payment transactions'
85
+ raise UnsupportedAccountDetails, msg
86
+ else
87
+ { bank_code: @bank_code, account_number: @account_number }
88
+ end
89
+ end
90
+ end
91
+
92
+ class Rule000300 < BaseRule
93
+ def converted_details
94
+ if @account_number == '6161604670'
95
+ msg = 'Account does not support payment transactions'
96
+ raise UnsupportedAccountDetails, msg
97
+ else
98
+ { bank_code: @bank_code, account_number: @account_number }
99
+ end
100
+ end
101
+ end
102
+
103
+ class Rule000400 < BaseRule
104
+ include PseudoAccountNumberBehaviour
105
+
106
+ @pseudo_account_number_mapping = {
107
+ '0000000135' => '0990021440',
108
+ '0000001111' => '6600012020',
109
+ '0000001900' => '0920019005',
110
+ '0000007878' => '0780008006',
111
+ '0000008888' => '0250030942',
112
+ '0000009595' => '1653524703',
113
+ '0000097097' => '0013044150',
114
+ '0000112233' => '0630025819',
115
+ '0000336666' => '6604058903',
116
+ '0000484848' => '0920018963'
117
+ }
118
+ end
119
+
120
+ class Rule000503 < BaseRule
121
+ EXCEPTION_BANK_CODES = %w(
122
+ 10080900 25780022 42080082 54280023 65180005 79580099 12080000 25980027
123
+ 42680081 54580020 65380003 80080000 13080000 26080024 43080083 54680022
124
+ 66280053 81080000 14080000 26281420 44080055 55080065 66680013 82080000
125
+ 15080000 26580070 44080057 57080070 67280051 83080000 16080000 26880063
126
+ 44580070 58580074 69280035 84080000 17080000 26981062 45080060 59080090
127
+ 70080056 85080200 18080000 28280012 46080010 60080055 70080057 86080055
128
+ 20080055 29280011 47880031 60080057 70380006 86080057 20080057 30080055
129
+ 49080025 60380002 71180005 87080000 21080050 30080057 50080055 60480008
130
+ 72180002 21280002 31080015 50080057 61080006 73180011 21480003 32080010
131
+ 50080082 61281007 73380004 21580000 33080030 50680002 61480001 73480013
132
+ 22180000 34080031 50780006 62080012 74180009 22181400 34280032 50880050
133
+ 62280012 74380007 22280000 36280071 51380040 63080015 75080003 24080000
134
+ 36580072 52080080 64080014 76080053 24180001 40080040 53080030 64380011
135
+ 79080052 25480021 41280043 54080021 65080009 79380051
136
+ ).freeze
137
+
138
+ PSEUDO_ACCOUNT_NUMBER_MAPPING = {
139
+ '30040000_0000000036' => '0261103600',
140
+ '47880031_0000000050' => '0519899900',
141
+ '47840065_0000000050' => '0150103000',
142
+ '47840065_0000000055' => '0150103000',
143
+ '70080000_0000000094' => '0928553201',
144
+ '70040041_0000000094' => '0212808000',
145
+ '47840065_0000000099' => '0150103000',
146
+ '37080040_0000000100' => '0269100000',
147
+ '38040007_0000000100' => '0119160000',
148
+ '37080040_0000000111' => '0215022000',
149
+ '51080060_0000000123' => '0012299300',
150
+ '36040039_0000000150' => '0161620000',
151
+ '68080030_0000000202' => '0416520200',
152
+ '30040000_0000000222' => '0348010002',
153
+ '38040007_0000000240' => '0109024000',
154
+ '69240075_0000000444' => '0445520000',
155
+ '60080000_0000000502' => '0901581400',
156
+ '60040071_0000000502' => '0525950200',
157
+ '55040022_0000000555' => '0211050000',
158
+ '39080005_0000000556' => '0204655600',
159
+ '39040013_0000000556' => '0106555600',
160
+ '57080070_0000000661' => '0604101200',
161
+ '26580070_0000000700' => '0710000000',
162
+ '50640015_0000000777' => '0222222200',
163
+ '30040000_0000000999' => '0123799900',
164
+ '86080000_0000001212' => '0480375900',
165
+ '37040044_0000001888' => '0212129101',
166
+ '25040066_0000001919' => '0141919100',
167
+ '10080000_0000001987' => '0928127700',
168
+ '50040000_0000002000' => '0728400300',
169
+ '20080000_0000002222' => '0903927200',
170
+ '38040007_0000003366' => '0385333000',
171
+ '37080040_0000004004' => '0233533500',
172
+ '37080040_0000004444' => '0233000300',
173
+ '43080083_0000004630' => '0825110100',
174
+ '50080000_0000006060' => '0096736100',
175
+ '10040000_0000007878' => '0267878700',
176
+ '10080000_0000008888' => '0928126501',
177
+ '50080000_0000009000' => '0026492100',
178
+ '79080052_0000009696' => '0300021700',
179
+ '79040047_0000009696' => '0680210200',
180
+ '39080005_0000009800' => '0208457000',
181
+ '50080000_0000042195' => '0900333200',
182
+ '32040024_0000047800' => '0155515000',
183
+ '37080040_0000055555' => '0263602501',
184
+ '38040007_0000055555' => '0305555500',
185
+ '50080000_0000101010' => '0090003500',
186
+ '50040000_0000101010' => '0311011100',
187
+ '37040044_0000102030' => '0222344400',
188
+ '86080000_0000121200' => '0480375900',
189
+ '66280053_0000121212' => '0625242400',
190
+ '16080000_0000123456' => '0012345600',
191
+ '29080010_0000124124' => '0107502000',
192
+ '37080040_0000182002' => '0216603302',
193
+ '12080000_0000212121' => '4050462200',
194
+ '37080040_0000300000' => '0983307900',
195
+ '37040044_0000300000' => '0300000700',
196
+ '37080040_0000333333' => '0270330000',
197
+ '38040007_0000336666' => '0105232300',
198
+ '55040022_0000343434' => '0217900000',
199
+ '85080000_0000400000' => '0459488501',
200
+ '37080040_0000414141' => '0041414100',
201
+ '38040007_0000414141' => '0108000100',
202
+ '20080000_0000505050' => '0500100600',
203
+ '37080040_0000555666' => '0055566600',
204
+ '20080000_0000666666' => '0900732500',
205
+ '30080000_0000700000' => '0800005000',
206
+ '70080000_0000700000' => '0750055500',
207
+ '70080000_0000900000' => '0319966601',
208
+ '37080040_0000909090' => '0269100000',
209
+ '38040007_0000909090' => '0119160000',
210
+ '70080000_0000949494' => '0575757500',
211
+ '70080000_0001111111' => '0448060000',
212
+ '70040041_0001111111' => '0152140000',
213
+ '10080000_0001234567' => '0920192001',
214
+ '38040007_0001555555' => '0258266600',
215
+ '76040061_0002500000' => '0482146800',
216
+ '16080000_0003030400' => '4205227110',
217
+ '37080040_0005555500' => '0263602501',
218
+ '75040062_0006008833' => '0600883300',
219
+ '12080000_0007654321' => '0144000700',
220
+ '70080000_0007777777' => '0443540000',
221
+ '70040041_0007777777' => '0213600000',
222
+ '64140036_0008907339' => '0890733900',
223
+ '70080000_0009000000' => '0319966601',
224
+ '61080006_0009999999' => '0202427500',
225
+ '12080000_0012121212' => '4101725100',
226
+ '29080010_0012412400' => '0107502000',
227
+ '34280032_0014111935' => '0645753800',
228
+ '38040007_0043434343' => '0118163500',
229
+ '30080000_0070000000' => '0800005000',
230
+ '70080000_0070000000' => '0750055500',
231
+ '44040037_0111111111' => '0320565500',
232
+ '70040041_0400500500' => '0400500500',
233
+ '60080000_0500500500' => '0901581400',
234
+ '60040071_0500500500' => '0512700600'
235
+ }.freeze
236
+
237
+ def converted_details
238
+ updated_account_number =
239
+ if PSEUDO_ACCOUNT_NUMBER_MAPPING.key?(combined_bank_details)
240
+ converted_pseudo_account_number
241
+ else
242
+ padded_account_number_for_validity
243
+ end
244
+
245
+ if EXCEPTION_BANK_CODES.include?(@bank_code) &&
246
+ updated_account_number.to_i.between?(998000000, 999499999)
247
+ msg = 'Account does not support payment transactions'
248
+ raise UnsupportedAccountDetails, msg
249
+ end
250
+
251
+ { bank_code: @bank_code, account_number: updated_account_number }
252
+ end
253
+
254
+ private
255
+
256
+ def combined_bank_details
257
+ "#{@bank_code}_#{@account_number.rjust(10, '0')}"
258
+ end
259
+
260
+ def converted_pseudo_account_number
261
+ PSEUDO_ACCOUNT_NUMBER_MAPPING[combined_bank_details]
262
+ end
263
+
264
+ def padded_account_number_for_validity
265
+ unpadded_account_number = @account_number.gsub(/\A0+/, '')
266
+
267
+ case GermanDetailsConverter.rules[@bank_code][:check_digit_rule]
268
+ when '13'
269
+ if unpadded_account_number.size.between?(6, 7)
270
+ unpadded_account_number + '00'
271
+ else @account_number
272
+ end
273
+ when '76'
274
+ case unpadded_account_number.size
275
+ when 7..8
276
+ if Check76.new(@account_number).valid? then @account_number
277
+ else unpadded_account_number + '00'
278
+ end
279
+ when 5..6 then unpadded_account_number + '00'
280
+ else @account_number
281
+ end
282
+ else @account_number
283
+ end
284
+ end
285
+
286
+ class Check76
287
+ def initialize(account_number)
288
+ @account_number = account_number.rjust(10, '0')
289
+ end
290
+
291
+ def valid?
292
+ return false unless valid_length? && valid_account_type?
293
+ [master_number[-1].to_i, 10].include?(remainder)
294
+ end
295
+
296
+ private
297
+
298
+ def master_number
299
+ @account_number.slice(1, 7).gsub(/\A0+/, '')
300
+ end
301
+
302
+ def remainder
303
+ sum_of_weighted_values % 11
304
+ end
305
+
306
+ def sum_of_weighted_values
307
+ weighted_values.reduce(0, &:+)
308
+ end
309
+
310
+ def weighted_values
311
+ weights = [2, 3, 4, 5, 6, 7, 8]
312
+
313
+ master_number[0..-2].reverse.chars.map.with_index do |digit, i|
314
+ digit.to_i * weights[i]
315
+ end
316
+ end
317
+
318
+ def valid_account_type?
319
+ [0, 4, 6, 7, 8, 9].include? @account_number[0].to_i
320
+ end
321
+
322
+ def valid_length?
323
+ [5, 6, 7].include? master_number.size
324
+ end
325
+ end
326
+ end
327
+
328
+ class Rule000600 < BaseRule
329
+ include PseudoAccountNumberBehaviour
330
+
331
+ @pseudo_account_number_mapping = {
332
+ '0001111111' => '0020228888',
333
+ '0007777777' => '0903286003',
334
+ '0034343434' => '1000506517',
335
+ '0000070000' => '0018180018'
336
+ }
337
+ end
338
+
339
+ class Rule000700 < BaseRule
340
+ include PseudoAccountNumberBehaviour
341
+
342
+ @pseudo_account_number_mapping = {
343
+ '0000000111' => '0000001115',
344
+ '0000000221' => '0023002157',
345
+ '0000001888' => '0018882068',
346
+ '0000002006' => '1900668508',
347
+ '0000002626' => '1900730100',
348
+ '0000003004' => '1900637016',
349
+ '0000003636' => '0023002447',
350
+ '0000004000' => '0000004028',
351
+ '0000004444' => '0000017368',
352
+ '0000005050' => '0000073999',
353
+ '0000008888' => '1901335750',
354
+ '0000030000' => '0009992959',
355
+ '0000043430' => '1901693331',
356
+ '0000046664' => '1900399856',
357
+ '0000055555' => '0034407379',
358
+ '0000102030' => '1900480466',
359
+ '0000151515' => '0057762957',
360
+ '0000222222' => '0002222222',
361
+ '0000300000' => '0009992959',
362
+ '0000333333' => '0000033217',
363
+ '0000414141' => '0000092817',
364
+ '0000606060' => '0000091025',
365
+ '0000909090' => '0000090944',
366
+ '0002602024' => '0005602024',
367
+ '0003000000' => '0009992959',
368
+ '0007777777' => '0002222222',
369
+ '0008090100' => '0000038901',
370
+ '0014141414' => '0043597665',
371
+ '0015000023' => '0015002223',
372
+ '0015151515' => '0057762957',
373
+ '0022222222' => '0002222222',
374
+ '0200820082' => '1901783868',
375
+ '0222220022' => '0002222222'
376
+ }
377
+ end
378
+
379
+ class Rule000800 < BaseRule
380
+ def converted_details
381
+ { bank_code: '50020200', account_number: @account_number }
382
+ end
383
+ end
384
+
385
+ class Rule000900 < BaseRule
386
+ def converted_details
387
+ updated_account_number =
388
+ if @account_number.rjust(10, '0').slice(0, 4) == '1116'
389
+ "3047#{@account_number.rjust(10, '0').slice(4, 6)}"
390
+ else
391
+ @account_number
392
+ end
393
+
394
+ { bank_code: '68351557', account_number: updated_account_number }
395
+ end
396
+ end
397
+
398
+ class Rule001001 < BaseRule
399
+ PSEUDO_ACCOUNT_NUMBER_MAPPING = {
400
+ '50050201_0000002000' => '0000222000',
401
+ '50050201_0000800000' => '0000180802'
402
+ }.freeze
403
+
404
+ BANK_CODE_MAPPING = {
405
+ '50050222' => '50050201'
406
+ }.freeze
407
+
408
+ def converted_details
409
+ updated_account_number = PSEUDO_ACCOUNT_NUMBER_MAPPING.fetch(
410
+ "#{@bank_code}_#{@account_number.rjust(10, '0')}",
411
+ @account_number
412
+ )
413
+ updated_bank_code = BANK_CODE_MAPPING.fetch(@bank_code, @bank_code)
414
+
415
+ { bank_code: updated_bank_code, account_number: updated_account_number }
416
+ end
417
+ end
418
+
419
+ class Rule001100 < BaseRule
420
+ include PseudoAccountNumberBehaviour
421
+
422
+ @pseudo_account_number_mapping = {
423
+ '0000001000' => '0008010001',
424
+ '0000047800' => '0000047803'
425
+ }
426
+ end
427
+
428
+ class Rule001201 < BaseRule
429
+ def converted_details
430
+ { bank_code: '50050000', account_number: @account_number }
431
+ end
432
+ end
433
+
434
+ class Rule001301 < BaseRule
435
+ def converted_details
436
+ { bank_code: '30050000', account_number: @account_number }
437
+ end
438
+ end
439
+
440
+ class Rule001400 < BaseRule
441
+ def converted_details
442
+ { bank_code: '30060601', account_number: @account_number }
443
+ end
444
+ end
445
+
446
+ class Rule001501 < BaseRule
447
+ include PseudoAccountNumberBehaviour
448
+
449
+ @pseudo_account_number_mapping = {
450
+ '0000000094' => '3008888018',
451
+ '0000000556' => '0000101010',
452
+ '0000000888' => '0031870011',
453
+ '0000004040' => '4003600101',
454
+ '0000005826' => '1015826017',
455
+ '0000025000' => '0025000110',
456
+ '0000393393' => '0033013019',
457
+ '0000444555' => '0032230016',
458
+ '0000603060' => '6002919018',
459
+ '0002120041' => '0002130041',
460
+ '0080868086' => '4007375013',
461
+ '0400569017' => '4000569017'
462
+ }
463
+ end
464
+
465
+ class Rule001600 < BaseRule
466
+ include PseudoAccountNumberBehaviour
467
+
468
+ @pseudo_account_number_mapping = { '0000300000' => '0018128012' }
469
+ end
470
+
471
+ class Rule001700 < BaseRule
472
+ include PseudoAccountNumberBehaviour
473
+
474
+ @pseudo_account_number_mapping = {
475
+ '0000000100' => '2009090013',
476
+ '0000000111' => '2111111017',
477
+ '0000000240' => '2100240010',
478
+ '0000004004' => '2204004016',
479
+ '0000004444' => '2044444014',
480
+ '0000006060' => '2016060014',
481
+ '0000102030' => '1102030016',
482
+ '0000333333' => '2033333016',
483
+ '0000909090' => '2009090013',
484
+ '0050005000' => '5000500013'
485
+ }
486
+ end
487
+
488
+ class Rule001800 < BaseRule
489
+ include PseudoAccountNumberBehaviour
490
+
491
+ @pseudo_account_number_mapping = {
492
+ '0000000556' => '0120440110',
493
+ '5435435430' => '0543543543',
494
+ '0000002157' => '0121787016',
495
+ '0000009800' => '0120800019',
496
+ '0000202050' => '1221864014'
497
+ }
498
+ end
499
+
500
+ class Rule001900 < BaseRule
501
+ def converted_details
502
+ { bank_code: '50120383', account_number: @account_number }
503
+ end
504
+ end
505
+
506
+ class Rule002002 < BaseRule
507
+ def converted_details
508
+ unpadded_account_number = @account_number.gsub(/\A0+/, '')
509
+
510
+ if unpadded_account_number == '9999' && @bank_code == '50070010'
511
+ return { bank_code: '50070010', account_number: '92777202' }
512
+ end
513
+
514
+ updated_account_number =
515
+ case unpadded_account_number.size
516
+ when 5, 6 then unpadded_account_number + '00'
517
+ when 7 then
518
+ if Check63.new(unpadded_account_number + '00').valid?
519
+ unpadded_account_number + '00'
520
+ else
521
+ unpadded_account_number
522
+ end
523
+ when 8, 9 then unpadded_account_number
524
+ else
525
+ msg = 'Account does not support payment transactions'
526
+ raise UnsupportedAccountDetails, msg
527
+ end
528
+
529
+ { bank_code: @bank_code, account_number: updated_account_number }
530
+ end
531
+
532
+ class Check63
533
+ # A Deutsche Bank specific variant of Check 63
534
+ def initialize(account_number)
535
+ @account_number = account_number.dup.rjust(10, '0')
536
+ end
537
+
538
+ def valid?
539
+ expected_check_digit = (10 - remainder) % 10
540
+ expected_check_digit == @account_number[-3].to_i
541
+ end
542
+
543
+ private
544
+
545
+ def remainder
546
+ sum_of_weighted_digits % 10
547
+ end
548
+
549
+ def sum_of_weighted_digits
550
+ weighted_digits.reduce(0, &:+)
551
+ end
552
+
553
+ def weighted_digits
554
+ weighted_values.flat_map { |value| value.to_s.chars.map(&:to_i) }
555
+ end
556
+
557
+ def weighted_values
558
+ weights = [2, 1, 2, 1, 2, 1]
559
+
560
+ @account_number.slice(1, 6).reverse.chars.map.with_index do |digit, i|
561
+ digit.to_i * weights[i]
562
+ end
563
+ end
564
+ end
565
+ end
566
+
567
+ class Rule002101 < BaseRule
568
+ def converted_details
569
+ { bank_code: '36020030', account_number: @account_number }
570
+ end
571
+ end
572
+
573
+ class Rule002200 < BaseRule
574
+ include PseudoAccountNumberBehaviour
575
+
576
+ @pseudo_account_number_mapping = { '0001111111' => '2222200000' }
577
+ end
578
+
579
+ class Rule002300 < BaseRule
580
+ include PseudoAccountNumberBehaviour
581
+
582
+ @pseudo_account_number_mapping = { '0000000700' => '1000700800' }
583
+ end
584
+
585
+ class Rule002400 < BaseRule
586
+ include PseudoAccountNumberBehaviour
587
+
588
+ @pseudo_account_number_mapping = {
589
+ '0000000094' => '0000001694',
590
+ '0000000248' => '0000017248',
591
+ '0000000345' => '0000017345',
592
+ '0000000400' => '0000014400'
593
+ }
594
+ end
595
+
596
+ class Rule002500 < BaseRule
597
+ def converted_details
598
+ { bank_code: '60050101', account_number: @account_number }
599
+ end
600
+ end
601
+
602
+ class Rule002600 < Rule000000
603
+ # Rule 0026 is actually about modulus checking, not IBAN construction
604
+ end
605
+
606
+ class Rule002700 < Rule000000
607
+ # Rule 0027 is actually about modulus checking, not IBAN construction
608
+ end
609
+
610
+ class Rule002800 < BaseRule
611
+ def converted_details
612
+ { bank_code: '25050180', account_number: @account_number }
613
+ end
614
+ end
615
+
616
+ class Rule002900 < BaseRule
617
+ def converted_details
618
+ updated_account_number =
619
+ if @account_number.size == 10 && @account_number[3] == '0'
620
+ "0#{@account_number.slice(0, 3)}#{@account_number.slice(4, 6)}"
621
+ else
622
+ @account_number
623
+ end
624
+
625
+ { bank_code: @bank_code, account_number: updated_account_number }
626
+ end
627
+ end
628
+
629
+ class Rule003000 < Rule000000
630
+ # Rule 0030 is actually about modulus checking, not IBAN construction
631
+ end
632
+
633
+ class Rule003101 < BaseRule
634
+ # This rule appears to be obsolete - no entries in the BLZ use it. The
635
+ # table below, which maps old Hypo bank codes to new ones, is used by
636
+ # other checks though.
637
+ #
638
+ BANK_CODE_MAPPING = {
639
+ '100' => '76020070', '101' => '10020890', '102' => '78320076',
640
+ '103' => '79320075', '104' => '76320072', '105' => '79020076',
641
+ '106' => '79320075', '107' => '79320075', '108' => '77320072',
642
+ '109' => '79320075', '110' => '76220073', '111' => '76020070',
643
+ '112' => '79320075', '113' => '76020070', '114' => '76020070',
644
+ '115' => '76520071', '117' => '77120073', '118' => '76020070',
645
+ '119' => '75320075', '120' => '72120078', '121' => '76220073',
646
+ '122' => '76320072', '123' => '76420080', '124' => '76320072',
647
+ '125' => '79520070', '126' => '77320072', '127' => '78020070',
648
+ '128' => '78020070', '129' => '77120073', '130' => '78020070',
649
+ '131' => '78020070', '132' => '60020290', '134' => '78020070',
650
+ '135' => '77020070', '136' => '79520070', '137' => '79320075',
651
+ '138' => '61120286', '139' => '66020286', '140' => '79020076',
652
+ '142' => '64020186', '143' => '60020290', '144' => '79020076',
653
+ '145' => '66020286', '146' => '72120078', '147' => '72223182',
654
+ '148' => '76520071', '149' => '79020076', '150' => '76020070',
655
+ '151' => '76320072', '152' => '78320076', '154' => '70020270',
656
+ '155' => '76520071', '156' => '76020070', '157' => '10020890',
657
+ '158' => '70020270', '159' => '54520194', '160' => '70020270',
658
+ '161' => '54520194', '162' => '70020270', '163' => '70020270',
659
+ '164' => '70020270', '166' => '71120078', '167' => '74320073',
660
+ '167' => '74320073', '168' => '70320090', '169' => '79020076',
661
+ '170' => '70020270', '172' => '70020270', '174' => '70020270',
662
+ '175' => '72120078', '176' => '74020074', '177' => '74320073',
663
+ '178' => '70020270', '181' => '77320072', '182' => '79520070',
664
+ '183' => '70020270', '185' => '70020270', '186' => '79020076',
665
+ '188' => '70020270', '189' => '70020270', '190' => '76020070',
666
+ '191' => '77020070', '192' => '70025175', '193' => '85020086',
667
+ '194' => '76020070', '196' => '72020070', '198' => '76320072',
668
+ '199' => '70020270', '201' => '76020070', '202' => '76020070',
669
+ '203' => '76020070', '204' => '76020070', '205' => '79520070',
670
+ '206' => '79520070', '207' => '71120078', '208' => '73120075',
671
+ '209' => '18020086', '210' => '10020890', '211' => '60020290',
672
+ '212' => '51020186', '214' => '75020073', '215' => '63020086',
673
+ '216' => '75020073', '217' => '79020076', '218' => '59020090',
674
+ '219' => '79520070', '220' => '73322380', '221' => '73120075',
675
+ '222' => '73421478', '223' => '74320073', '224' => '73322380',
676
+ '225' => '74020074', '227' => '75020073', '228' => '71120078',
677
+ '229' => '80020086', '230' => '72120078', '231' => '72020070',
678
+ '232' => '75021174', '233' => '71020072', '234' => '71022182',
679
+ '235' => '74320073', '236' => '71022182', '237' => '76020070',
680
+ '238' => '63020086', '239' => '70020270', '240' => '75320075',
681
+ '241' => '76220073', '243' => '72020070', '245' => '72120078',
682
+ '246' => '74320073', '247' => '60020290', '248' => '85020086',
683
+ '249' => '73321177', '250' => '73420071', '251' => '70020270',
684
+ '252' => '70020270', '253' => '70020270', '254' => '10020890',
685
+ '255' => '50820292', '256' => '71022182', '257' => '83020086',
686
+ '258' => '79320075', '259' => '71120077', '260' => '10020890',
687
+ '261' => '70025175', '262' => '72020070', '264' => '74020074',
688
+ '267' => '63020086', '268' => '70320090', '269' => '71122183',
689
+ '270' => '82020086', '271' => '75020073', '272' => '73420071',
690
+ '274' => '63020086', '276' => '70020270', '277' => '74320073',
691
+ '278' => '71120077', '279' => '10020890', '281' => '71120078',
692
+ '282' => '70020270', '283' => '72020070', '284' => '79320075',
693
+ '286' => '54520194', '287' => '70020270', '288' => '75220070',
694
+ '291' => '77320072', '292' => '76020070', '293' => '72020070',
695
+ '294' => '54520194', '295' => '70020270', '296' => '70020270',
696
+ '299' => '72020070', '301' => '85020086', '302' => '54520194',
697
+ '304' => '70020270', '308' => '70020270', '309' => '54520194',
698
+ '310' => '72020070', '312' => '74120071', '313' => '76320072',
699
+ '314' => '70020270', '315' => '70020270', '316' => '70020270',
700
+ '317' => '70020270', '318' => '70020270', '320' => '71022182',
701
+ '321' => '75220070', '322' => '79520070', '324' => '70020270',
702
+ '326' => '85020086', '327' => '72020070', '328' => '72020070',
703
+ '329' => '70020270', '330' => '76020070', '331' => '70020270',
704
+ '333' => '70020270', '334' => '75020073', '335' => '70020270',
705
+ '337' => '80020086', '341' => '10020890', '342' => '10020890',
706
+ '344' => '70020270', '345' => '77020070', '346' => '76020070',
707
+ '350' => '79320075', '351' => '79320075', '352' => '70020270',
708
+ '353' => '70020270', '354' => '72223182', '355' => '72020070',
709
+ '356' => '70020270', '358' => '54220091', '359' => '76220073',
710
+ '360' => '80020087', '361' => '70020270', '362' => '70020270',
711
+ '363' => '70020270', '366' => '72220074', '367' => '70020270',
712
+ '368' => '10020890', '369' => '76520071', '370' => '85020086',
713
+ '371' => '70020270', '373' => '70020270', '374' => '73120075',
714
+ '375' => '70020270', '379' => '70020270', '380' => '70020270',
715
+ '381' => '70020270', '382' => '79520070', '383' => '72020070',
716
+ '384' => '72020070', '386' => '70020270', '387' => '70020270',
717
+ '389' => '70020270', '390' => '67020190', '391' => '70020270',
718
+ '392' => '70020270', '393' => '54520194', '394' => '70020270',
719
+ '396' => '70020270', '398' => '66020286', '399' => '87020088',
720
+ '401' => '30220190', '402' => '36020186', '403' => '38020090',
721
+ '404' => '30220190', '405' => '68020186', '406' => '48020086',
722
+ '407' => '37020090', '408' => '68020186', '409' => '10020890',
723
+ '410' => '66020286', '411' => '60420186', '412' => '57020086',
724
+ '422' => '70020270', '423' => '70020270', '424' => '76020070',
725
+ '426' => '70025175', '427' => '50320191', '428' => '70020270',
726
+ '429' => '85020086', '432' => '70020270', '434' => '60020290',
727
+ '435' => '76020070', '436' => '76020070', '437' => '70020270',
728
+ '438' => '70020270', '439' => '70020270', '440' => '70020270',
729
+ '441' => '70020270', '442' => '85020086', '443' => '55020486',
730
+ '444' => '50520190', '446' => '80020086', '447' => '70020270',
731
+ '450' => '30220190', '451' => '44020090', '452' => '70020270',
732
+ '453' => '70020270', '456' => '10020890', '457' => '87020086',
733
+ '458' => '54520194', '459' => '61120286', '460' => '70020270',
734
+ '461' => '70020270', '462' => '70020270', '463' => '70020270',
735
+ '465' => '70020270', '466' => '10020890', '467' => '10020890',
736
+ '468' => '70020270', '469' => '60320291', '470' => '65020186',
737
+ '471' => '84020087', '472' => '76020070', '473' => '74020074',
738
+ '476' => '78320076', '477' => '78320076', '478' => '87020088',
739
+ '480' => '70020270', '481' => '70020270', '482' => '84020087',
740
+ '484' => '70020270', '485' => '50320191', '486' => '70020270',
741
+ '488' => '67220286', '489' => '10020890', '490' => '10020890',
742
+ '491' => '16020086', '492' => '10020890', '494' => '79020076',
743
+ '495' => '87020088', '497' => '87020087', '499' => '79020076',
744
+ '502' => '10020890', '503' => '10020890', '505' => '70020270',
745
+ '506' => '10020890', '507' => '87020086', '508' => '86020086',
746
+ '509' => '83020087', '510' => '80020086', '511' => '83020086',
747
+ '513' => '85020086', '515' => '17020086', '518' => '82020086',
748
+ '519' => '83020086', '522' => '10020890', '523' => '70020270',
749
+ '524' => '85020086', '525' => '70020270', '527' => '82020088',
750
+ '528' => '10020890', '530' => '10020890', '531' => '10020890',
751
+ '533' => '50320191', '534' => '70020270', '536' => '85020086',
752
+ '538' => '82020086', '540' => '65020186', '541' => '80020087',
753
+ '545' => '18020086', '546' => '10020890', '547' => '10020890',
754
+ '548' => '10020890', '549' => '82020087', '555' => '79020076',
755
+ '560' => '79320075', '567' => '86020086', '572' => '10020890',
756
+ '580' => '70020270', '581' => '70020270', '601' => '74320073',
757
+ '602' => '70020270', '603' => '70020270', '604' => '70020270',
758
+ '605' => '70020270', '606' => '70020270', '607' => '74320073',
759
+ '608' => '72020070', '609' => '72020070', '610' => '72020070',
760
+ '611' => '72020070', '612' => '71120077', '613' => '70020270',
761
+ '614' => '72020070', '615' => '70025175', '616' => '73420071',
762
+ '617' => '68020186', '618' => '73120075', '619' => '60020290',
763
+ '620' => '71120077', '621' => '71120077', '622' => '74320073',
764
+ '623' => '72020070', '624' => '71020072', '625' => '71023173',
765
+ '626' => '71020072', '627' => '71021270', '628' => '71120077',
766
+ '629' => '73120075', '630' => '71121176', '631' => '71022182',
767
+ '632' => '70020270', '633' => '74320073', '634' => '70020270',
768
+ '635' => '70320090', '636' => '70320090', '637' => '72120078',
769
+ '638' => '72120078', '640' => '70020270', '641' => '70020270',
770
+ '643' => '74320073', '644' => '70020270', '645' => '70020270',
771
+ '646' => '70020270', '647' => '70020270', '648' => '72120078',
772
+ '649' => '72122181', '650' => '54520194', '652' => '71021270',
773
+ '653' => '70020270', '654' => '70020270', '655' => '72120078',
774
+ '656' => '71120078', '657' => '71020072', '658' => '68020186',
775
+ '659' => '54520194', '660' => '54620093', '661' => '74320073',
776
+ '662' => '73120075', '663' => '70322192', '664' => '72120078',
777
+ '665' => '70321194', '666' => '73322380', '667' => '60020290',
778
+ '668' => '60020290', '669' => '73320073', '670' => '75020073',
779
+ '671' => '74220075', '672' => '74020074', '673' => '74020074',
780
+ '674' => '74120071', '675' => '74020074', '676' => '74020074',
781
+ '677' => '72020070', '678' => '72020070', '679' => '54520194',
782
+ '680' => '71120077', '681' => '67020190', '682' => '78020070',
783
+ '683' => '71020072', '684' => '70020270', '685' => '70020270',
784
+ '686' => '70020270', '687' => '70020270', '688' => '70020270',
785
+ '689' => '70020270', '690' => '76520071', '692' => '70020270',
786
+ '693' => '73420071', '694' => '70021180', '695' => '70320090',
787
+ '696' => '74320073', '697' => '54020090', '698' => '73320073',
788
+ '710' => '30220190', '711' => '70020270', '712' => '10020890',
789
+ '714' => '76020070', '715' => '75020073', '717' => '74320073',
790
+ '718' => '87020086', '719' => '37020090', '720' => '30220190',
791
+ '723' => '77320072', '733' => '83020087', '798' => '70020270'
792
+ }.freeze
793
+ end
794
+
795
+ class Rule003200 < BaseRule
796
+ def converted_details
797
+ if @account_number.to_i.between?(800000000, 899999999)
798
+ msg = 'Account does not support payment transactions'
799
+ raise UnsupportedAccountDetails, msg
800
+ end
801
+
802
+ updated_bank_code = Rule003101::BANK_CODE_MAPPING.fetch(
803
+ @account_number.rjust(10, '0').slice(0, 3),
804
+ @bank_code
805
+ )
806
+
807
+ { bank_code: updated_bank_code, account_number: @account_number }
808
+ end
809
+ end
810
+
811
+ class Rule003301 < BaseRule
812
+ PSEUDO_ACCOUNT_NUMBER_MAPPING = {
813
+ '0000022222' => '5803435253',
814
+ '0001111111' => '0039908140',
815
+ '0000000094' => '0002711931',
816
+ '0007777777' => '5800522694',
817
+ '0000055555' => '5801800000'
818
+ }.freeze
819
+
820
+ def converted_details
821
+ updated_bank_code = Rule003101::BANK_CODE_MAPPING.fetch(
822
+ @account_number.rjust(10, '0').slice(0, 3),
823
+ @bank_code
824
+ )
825
+
826
+ updated_account_number = PSEUDO_ACCOUNT_NUMBER_MAPPING.fetch(
827
+ @account_number.rjust(10, '0'),
828
+ @account_number
829
+ )
830
+
831
+ { bank_code: updated_bank_code, account_number: updated_account_number }
832
+ end
833
+ end
834
+
835
+ class Rule003400 < BaseRule
836
+ PSEUDO_ACCOUNT_NUMBER_MAPPING = {
837
+ '0500500500' => '4340111112',
838
+ '0000000502' => '4340118001'
839
+ }.freeze
840
+
841
+ def converted_details
842
+ if @account_number.to_i.between?(800000000, 899999999)
843
+ msg = 'Account does not support payment transactions'
844
+ raise UnsupportedAccountDetails, msg
845
+ end
846
+
847
+ updated_bank_code = Rule003101::BANK_CODE_MAPPING.fetch(
848
+ @account_number.rjust(10, '0').slice(0, 3),
849
+ @bank_code
850
+ )
851
+
852
+ updated_account_number = PSEUDO_ACCOUNT_NUMBER_MAPPING.fetch(
853
+ @account_number.rjust(10, '0'),
854
+ @account_number
855
+ )
856
+
857
+ { bank_code: updated_bank_code, account_number: updated_account_number }
858
+ end
859
+ end
860
+
861
+ class Rule003501 < BaseRule
862
+ PSEUDO_ACCOUNT_NUMBER_MAPPING = { '0000009696' => '1490196966' }.freeze
863
+
864
+ def converted_details
865
+ if @account_number.to_i.between?(800000000, 899999999)
866
+ msg = 'Account does not support payment transactions'
867
+ raise UnsupportedAccountDetails, msg
868
+ end
869
+
870
+ updated_bank_code = Rule003101::BANK_CODE_MAPPING.fetch(
871
+ @account_number.rjust(10, '0').slice(0, 3),
872
+ @bank_code
873
+ )
874
+
875
+ updated_account_number = PSEUDO_ACCOUNT_NUMBER_MAPPING.fetch(
876
+ @account_number.rjust(10, '0'),
877
+ @account_number
878
+ )
879
+
880
+ { bank_code: updated_bank_code, account_number: updated_account_number }
881
+ end
882
+ end
883
+
884
+ class Rule003600 < BaseRule
885
+ def converted_details
886
+ updated_account_number =
887
+ case @account_number.to_i
888
+ when 100000..899999 then @account_number + '000'
889
+ when 30000000..59999999 then @account_number
890
+ when 100000000..899999999 then @account_number
891
+ when 1000000000..1999999999 then @account_number
892
+ when 3000000000..7099999999 then @account_number
893
+ when 8500000000..8599999999 then @account_number
894
+ when 9000000000..9999999999 then @account_number
895
+ else disallow
896
+ end
897
+
898
+ { bank_code: '20050000', account_number: updated_account_number }
899
+ end
900
+
901
+ private
902
+
903
+ def disallow
904
+ msg = 'Account does not support payment transactions'
905
+ raise UnsupportedAccountDetails, msg
906
+ end
907
+ end
908
+
909
+ class Rule003700 < BaseRule
910
+ def converted_details
911
+ { bank_code: '30010700', account_number: @account_number }
912
+ end
913
+ end
914
+
915
+ class Rule003800 < BaseRule
916
+ def converted_details
917
+ { bank_code: '28590075', account_number: @account_number }
918
+ end
919
+ end
920
+
921
+ class Rule003900 < BaseRule
922
+ def converted_details
923
+ { bank_code: '28020050', account_number: @account_number }
924
+ end
925
+ end
926
+
927
+ class Rule004001 < BaseRule
928
+ def converted_details
929
+ { bank_code: '68052328', account_number: @account_number }
930
+ end
931
+ end
932
+
933
+ class Rule004100 < BaseRule
934
+ def converted_details
935
+ { bank_code: '50060400', account_number: '0000011404' }
936
+ end
937
+ end
938
+
939
+ class Rule004200 < BaseRule
940
+ def converted_details
941
+ unpadded_account_number = @account_number.gsub(/\A0+/, '')
942
+
943
+ if @account_number.to_i.between?(50462000, 50463999) ||
944
+ @account_number.to_i.between?(50469000, 50469999)
945
+ { bank_code: @bank_code, account_number: @account_number }
946
+ elsif unpadded_account_number.size != 8 ||
947
+ unpadded_account_number[3] != '0' ||
948
+ %w(00000 00999).include?(unpadded_account_number.slice(3, 5))
949
+ msg = 'Account does not support payment transactions'
950
+ raise UnsupportedAccountDetails, msg
951
+ else
952
+ { bank_code: @bank_code, account_number: @account_number }
953
+ end
954
+ end
955
+ end
956
+
957
+ class Rule004301 < BaseRule
958
+ def converted_details
959
+ { bank_code: '66650085', account_number: @account_number }
960
+ end
961
+ end
962
+
963
+ class Rule004400 < BaseRule
964
+ include PseudoAccountNumberBehaviour
965
+
966
+ @pseudo_account_number_mapping = { '0000000202' => '0002282022' }
967
+ end
968
+
969
+ class Rule004501 < Rule000000
970
+ # Rule 004501 is actually about BICs, and the BIC details are already
971
+ # included correctly in the Bankleitzahl file and SWIFT databases
972
+ end
973
+
974
+ class Rule004600 < BaseRule
975
+ def converted_details
976
+ { bank_code: '31010833', account_number: @account_number }
977
+ end
978
+ end
979
+
980
+ class Rule004700 < BaseRule
981
+ def converted_details
982
+ unpadded_account_number = @account_number.gsub(/\A0+/, '')
983
+
984
+ updated_account_number =
985
+ if unpadded_account_number.size == 8
986
+ unpadded_account_number.ljust(10, '0')
987
+ else
988
+ unpadded_account_number.rjust(10, '0')
989
+ end
990
+
991
+ { bank_code: @bank_code, account_number: updated_account_number }
992
+ end
993
+ end
994
+
995
+ class Rule004800 < BaseRule
996
+ def converted_details
997
+ { bank_code: '36010200', account_number: @account_number }
998
+ end
999
+ end
1000
+
1001
+ class Rule004900 < BaseRule
1002
+ PSEUDO_ACCOUNT_NUMBER_MAPPING = {
1003
+ '0000000036' => '0002310113',
1004
+ '0000000936' => '0002310113',
1005
+ '0000000999' => '0001310113',
1006
+ '0000006060' => '0000160602'
1007
+ }.freeze
1008
+
1009
+ def converted_details
1010
+ padded_account_number = @account_number.rjust(10, '0')
1011
+
1012
+ updated_account_number =
1013
+ if padded_account_number[4] == '9'
1014
+ "#{padded_account_number[4, 6]}#{padded_account_number[0, 4]}"
1015
+ else
1016
+ @account_number
1017
+ end
1018
+
1019
+ updated_account_number = PSEUDO_ACCOUNT_NUMBER_MAPPING.fetch(
1020
+ updated_account_number.rjust(10, '0'),
1021
+ updated_account_number
1022
+ )
1023
+
1024
+ { bank_code: @bank_code, account_number: updated_account_number }
1025
+ end
1026
+ end
1027
+
1028
+ class Rule005000 < BaseRule
1029
+ def converted_details
1030
+ { bank_code: '28550000', account_number: @account_number }
1031
+ end
1032
+ end
1033
+
1034
+ class Rule005100 < BaseRule
1035
+ include PseudoAccountNumberBehaviour
1036
+
1037
+ @pseudo_account_number_mapping = {
1038
+ '0000000333' => '7832500881',
1039
+ '0000000502' => '0001108884',
1040
+ '0500500500' => '0005005000',
1041
+ '0502502502' => '0001108884'
1042
+ }
1043
+ end
1044
+
1045
+ class Rule005200 < BaseRule
1046
+ PSEUDO_ACCOUNT_NUMBER_MAPPING = {
1047
+ '67220020_5308810004' => '0002662604',
1048
+ '67220020_5308810000' => '0002659600',
1049
+ '67020020_5203145700' => '7496510994',
1050
+ '69421020_6208908100' => '7481501341',
1051
+ '66620020_4840404000' => '7498502663',
1052
+ '64120030_1201200100' => '7477501214',
1053
+ '64020030_1408050100' => '7469534505',
1054
+ '63020130_1112156300' => '0004475655',
1055
+ '62030050_7002703200' => '7406501175',
1056
+ '69220020_6402145400' => '7485500252'
1057
+ }.freeze
1058
+
1059
+ def converted_details
1060
+ updated_account_number = PSEUDO_ACCOUNT_NUMBER_MAPPING.fetch(
1061
+ "#{@bank_code}_#{@account_number.rjust(10, '0')}",
1062
+ nil
1063
+ )
1064
+
1065
+ if updated_account_number.nil?
1066
+ msg = "Bank code #{@bank_code} is not used for payment transactions"
1067
+ raise UnsupportedAccountDetails, msg
1068
+ end
1069
+
1070
+ { bank_code: '60050101', account_number: updated_account_number }
1071
+ end
1072
+ end
1073
+
1074
+ class Rule005300 < BaseRule
1075
+ PSEUDO_ACCOUNT_NUMBER_MAPPING = {
1076
+ '55050000_0000035000' => '7401555913',
1077
+ '55050000_0119345106' => '7401555906',
1078
+ '55050000_0000000908' => '7401507480',
1079
+ '55050000_0000000901' => '7401507497',
1080
+ '55050000_0000000910' => '7401507466',
1081
+ '55050000_0000035100' => '7401555913',
1082
+ '55050000_0000000902' => '7401507473',
1083
+ '55050000_0000044000' => '7401555872',
1084
+ '55050000_0110132511' => '7401550530',
1085
+ '55050000_0110024270' => '7401501266',
1086
+ '55050000_0000003500' => '7401555913',
1087
+ '55050000_0110050002' => '7401502234',
1088
+ '55050000_0055020100' => '7401555872',
1089
+ '55050000_0110149226' => '7401512248',
1090
+ '60020030_1047444300' => '7871538395',
1091
+ '60020030_1040748400' => '0001366705',
1092
+ '60020030_1000617900' => '0002009906',
1093
+ '60020030_1003340500' => '0002001155',
1094
+ '60020030_1002999900' => '0002588991',
1095
+ '60020030_1004184600' => '7871513509',
1096
+ '60020030_1000919900' => '7871531505',
1097
+ '60020030_1054290000' => '7871521216',
1098
+ '60050000_0000001523' => '0001364934',
1099
+ '60050000_0000002811' => '0001367450',
1100
+ '60050000_0000002502' => '0001366705',
1101
+ '60050000_0000250412' => '7402051588',
1102
+ '60050000_0000003009' => '0001367924',
1103
+ '60050000_0000004596' => '0001372809',
1104
+ '60050000_0000003080' => '0002009906',
1105
+ '60050000_0001029204' => '0002782254',
1106
+ '60050000_0000003002' => '0001367924',
1107
+ '60050000_0000123456' => '0001362826',
1108
+ '60050000_0000002535' => '0001119897',
1109
+ '60050000_0000005500' => '0001375703',
1110
+ '66020020_4002401000' => '7495500967',
1111
+ '66020020_4000604100' => '0002810030',
1112
+ '66020020_4002015800' => '7495530102',
1113
+ '66020020_4003746700' => '7495501485',
1114
+ '66050000_0000086567' => '0001364934',
1115
+ '66050000_0000086345' => '7402046641',
1116
+ '66050000_0000085304' => '7402045439',
1117
+ '66050000_0000085990' => '7402051588',
1118
+ '86050000_0000001016' => '7461500128',
1119
+ '86050000_0000003535' => '7461505611',
1120
+ '86050000_0000002020' => '7461500018',
1121
+ '86050000_0000004394' => '7461505714'
1122
+ }.freeze
1123
+
1124
+ def converted_details
1125
+ updated_account_number = PSEUDO_ACCOUNT_NUMBER_MAPPING.fetch(
1126
+ "#{@bank_code}_#{@account_number.rjust(10, '0')}",
1127
+ nil
1128
+ )
1129
+
1130
+ {
1131
+ bank_code: updated_account_number.nil? ? @bank_code : '60050101',
1132
+ account_number: updated_account_number || @account_number
1133
+ }
1134
+ end
1135
+ end
1136
+
1137
+ class Rule005401 < BaseRule
1138
+ include PseudoAccountNumberBehaviour
1139
+
1140
+ @pseudo_account_number_mapping = {
1141
+ '0000000500' => '0000500500',
1142
+ '0000000502' => '0000502502',
1143
+ '0000018067' => '0000180670',
1144
+ '0000484848' => '0000484849',
1145
+ '0000636306' => '0000063606',
1146
+ '0000760440' => '0000160440',
1147
+ '0001018413' => '0010108413',
1148
+ '0002601577' => '0026015776',
1149
+ '0005005000' => '0000500500',
1150
+ '0010796740' => '0010796743',
1151
+ '0011796740' => '0011796743',
1152
+ '0012796740' => '0012796743',
1153
+ '0013796740' => '0013796743',
1154
+ '0014796740' => '0014796743',
1155
+ '0015796740' => '0015796743',
1156
+ '0016307000' => '0163107000',
1157
+ '0016610700' => '0166107000',
1158
+ '0016796740' => '0016796743',
1159
+ '0017796740' => '0017796743',
1160
+ '0018796740' => '0018796743',
1161
+ '0019796740' => '0019796743',
1162
+ '0020796740' => '0020796743',
1163
+ '0021796740' => '0021796743',
1164
+ '0022796740' => '0022796743',
1165
+ '0023796740' => '0023796743',
1166
+ '0024796740' => '0024796743',
1167
+ '0025796740' => '0025796743',
1168
+ '0026610700' => '0266107000',
1169
+ '0026796740' => '0026796743',
1170
+ '0027796740' => '0027796743',
1171
+ '0028796740' => '0028796743',
1172
+ '0029796740' => '0029796743',
1173
+ '0045796740' => '0045796743',
1174
+ '0050796740' => '0050796743',
1175
+ '0051796740' => '0051796743',
1176
+ '0052796740' => '0052796743',
1177
+ '0053796740' => '0053796743',
1178
+ '0054796740' => '0054796743',
1179
+ '0055796740' => '0055796743',
1180
+ '0056796740' => '0056796743',
1181
+ '0057796740' => '0057796743',
1182
+ '0058796740' => '0058796743',
1183
+ '0059796740' => '0059796743',
1184
+ '0060796740' => '0060796743',
1185
+ '0061796740' => '0061796743',
1186
+ '0062796740' => '0062796743',
1187
+ '0063796740' => '0063796743',
1188
+ '0064796740' => '0064796743',
1189
+ '0065796740' => '0065796743',
1190
+ '0066796740' => '0066796743',
1191
+ '0067796740' => '0067796743',
1192
+ '0068796740' => '0068796743',
1193
+ '0069796740' => '0069796743',
1194
+ '1761070000' => '0176107000',
1195
+ '2210531180' => '0201053180'
1196
+ }
1197
+ end
1198
+
1199
+ class Rule005500 < BaseRule
1200
+ def converted_details
1201
+ { bank_code: '25410200', account_number: @account_number }
1202
+ end
1203
+ end
1204
+
1205
+ class Rule005600 < BaseRule
1206
+ EXCEPTION_BANK_CODES = %w(
1207
+ 10010111 26510111 36210111 48010111 59010111 70010111 13010111 27010111
1208
+ 37010111 50010111 60010111 72010111 16010111 28010111 38010111 50510111
1209
+ 63010111 75010111 20010111 29010111 39010111 51010111 65310111 76010111
1210
+ 21010111 29210111 40010111 51310111 66010111 79010111 21210111 30010111
1211
+ 41010111 51410111 66610111 79510111 23010111 31010111 42010111 52010111
1212
+ 67010111 81010111 25010111 33010111 42610112 54210111 67210111 82010111
1213
+ 25410111 35010111 43010111 55010111 68010111 86010111 25910111 35211012
1214
+ 44010111 57010111 68310111 26010111 36010111 46010111 58510111 69010111
1215
+ ).freeze
1216
+
1217
+ PSEUDO_ACCOUNT_NUMBER_MAPPING = {
1218
+ '0000000036' => '1010240003',
1219
+ '0000000050' => '1328506100',
1220
+ '0000000099' => '1826063000',
1221
+ '0000000110' => '1015597802',
1222
+ '0000000240' => '1010240000',
1223
+ '0000000333' => '1011296100',
1224
+ '0000000555' => '1600220800',
1225
+ '0000000556' => '1000556100',
1226
+ '0000000606' => '1967153801',
1227
+ '0000000700' => '1070088000',
1228
+ '0000000777' => '1006015200',
1229
+ '0000000999' => '1010240001',
1230
+ '0000001234' => '1369152400',
1231
+ '0000001313' => '1017500000',
1232
+ '0000001888' => '1241113000',
1233
+ '0000001953' => '1026500901',
1234
+ '0000001998' => '1547620500',
1235
+ '0000002007' => '1026500907',
1236
+ '0000004004' => '1635100100',
1237
+ '0000004444' => '1304610900',
1238
+ '0000005000' => '1395676000',
1239
+ '0000005510' => '1611754300',
1240
+ '0000006060' => '1000400200',
1241
+ '0000006800' => '1296401301',
1242
+ '0000055555' => '1027758200',
1243
+ '0000060000' => '1005007001',
1244
+ '0000066666' => '1299807801',
1245
+ '0000102030' => '1837501600',
1246
+ '0000121212' => '1249461502',
1247
+ '0000130500' => '1413482100',
1248
+ '0000202020' => '1213431002',
1249
+ '0000414141' => '1010555101',
1250
+ '0000666666' => '1798758900',
1251
+ '0005000000' => '1403124100',
1252
+ '0500500500' => '1045720000'
1253
+ }.freeze
1254
+
1255
+ def converted_details
1256
+ updated_account_number = PSEUDO_ACCOUNT_NUMBER_MAPPING.fetch(
1257
+ @account_number.rjust(10, '0'),
1258
+ @account_number
1259
+ )
1260
+
1261
+ if updated_account_number.gsub(/\A0+/, '').size < 10 &&
1262
+ EXCEPTION_BANK_CODES.include?(@bank_code)
1263
+ msg = 'Account does not support payment transactions'
1264
+ raise UnsupportedAccountDetails, msg
1265
+ end
1266
+
1267
+ { bank_code: @bank_code, account_number: updated_account_number }
1268
+ end
1269
+ end
1270
+
1271
+ class Rule005700 < BaseRule
1272
+ def converted_details
1273
+ { bank_code: '66010200', account_number: @account_number }
1274
+ end
1275
+ end
1276
+ end
1277
+ end