ibandit 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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