ibandit 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +37 -0
- data/.rubocop.yml +10 -5
- data/.rubocop_todo.yml +13 -12
- data/CHANGELOG.md +23 -0
- data/Gemfile +0 -4
- data/README.md +1 -1
- data/Rakefile +8 -0
- data/data/german_iban_rules.yml +1099 -1594
- data/data/raw/BLZ2.txt +15947 -17888
- data/data/structures.yml +2 -2
- data/ibandit.gemspec +3 -2
- data/lib/ibandit.rb +1 -1
- data/lib/ibandit/check_digit.rb +1 -1
- data/lib/ibandit/german_details_converter.rb +22 -1
- data/lib/ibandit/iban.rb +20 -9
- data/lib/ibandit/local_details_cleaner.rb +7 -5
- data/lib/ibandit/version.rb +1 -1
- data/spec/fixtures/germany_integration_test_cases.json +23 -17
- data/spec/fixtures/germany_unit_test_cases.json +31 -6
- data/spec/ibandit/iban_spec.rb +27 -4
- data/spec/ibandit/local_details_cleaner_spec.rb +7 -1
- data/spec/ibandit/pseudo_iban_assembler_spec.rb +1 -1
- data/spec/ibandit/structure_spec.rb +1 -1
- metadata +22 -7
- data/.travis.yml +0 -16
data/data/structures.yml
CHANGED
@@ -95,7 +95,7 @@ BE:
|
|
95
95
|
:national_id_length: 3
|
96
96
|
:bban_format: "\\d{3}\\d{7}\\d{2}"
|
97
97
|
:bank_code_format: "\\d{3}"
|
98
|
-
:account_number_format: "\\d{7}\\d{2}"
|
98
|
+
:account_number_format: "\\d{7}\\d{2}\\d{3}"
|
99
99
|
:local_check_digit_position: 15
|
100
100
|
:local_check_digit_length: 2
|
101
101
|
BG:
|
@@ -902,7 +902,7 @@ US:
|
|
902
902
|
:branch_code_length: 0
|
903
903
|
:account_number_length: 17
|
904
904
|
:bank_code_format: "\\d{9}"
|
905
|
-
:account_number_format: "
|
905
|
+
:account_number_format: "_*\\d{1,17}"
|
906
906
|
:national_id_length: 9
|
907
907
|
:pseudo_iban_bank_code_length: 9
|
908
908
|
:pseudo_iban_branch_code_length: 0
|
data/ibandit.gemspec
CHANGED
@@ -3,13 +3,14 @@
|
|
3
3
|
require File.expand_path("lib/ibandit/version", __dir__)
|
4
4
|
|
5
5
|
Gem::Specification.new do |gem|
|
6
|
+
gem.add_development_dependency "gc_ruboconfig", "~> 2.17.0"
|
6
7
|
gem.add_development_dependency "nokogiri", "~> 1.6"
|
7
8
|
gem.add_development_dependency "pry", "~> 0.10"
|
8
9
|
gem.add_development_dependency "pry-nav", "~> 0.2"
|
9
10
|
gem.add_development_dependency "rspec", "~> 3.3"
|
10
11
|
gem.add_development_dependency "rspec-its", "~> 1.2"
|
11
|
-
gem.add_development_dependency "
|
12
|
-
gem.add_development_dependency "sax-machine",
|
12
|
+
gem.add_development_dependency "rspec_junit_formatter", "~> 0.4.1"
|
13
|
+
gem.add_development_dependency "sax-machine", "~> 1.3"
|
13
14
|
|
14
15
|
gem.add_runtime_dependency "i18n"
|
15
16
|
|
data/lib/ibandit.rb
CHANGED
data/lib/ibandit/check_digit.rb
CHANGED
@@ -517,7 +517,7 @@ module Ibandit
|
|
517
517
|
updated_account_number =
|
518
518
|
case unpadded_account_number.size
|
519
519
|
when 5, 6 then unpadded_account_number + "00"
|
520
|
-
when 7
|
520
|
+
when 7
|
521
521
|
if Check63.new(unpadded_account_number + "00").valid?
|
522
522
|
unpadded_account_number + "00"
|
523
523
|
else
|
@@ -957,6 +957,23 @@ module Ibandit
|
|
957
957
|
end
|
958
958
|
end
|
959
959
|
|
960
|
+
# New version of Rule004200 but with another range:
|
961
|
+
# For 10-digit Account Numbers, only the following Account Numbers are
|
962
|
+
# applicable to be issued / created into an IBAN with the
|
963
|
+
# standard-IBAN rule: nnn4400001 to nnn4499999
|
964
|
+
class Rule004201 < Rule004200
|
965
|
+
def converted_details
|
966
|
+
unpadded_account_number = @account_number.gsub(/\A0+/, "")
|
967
|
+
|
968
|
+
if unpadded_account_number.size == 10 &&
|
969
|
+
%w[4400001 4499999].include?(unpadded_account_number.slice(3, 10))
|
970
|
+
{ bank_code: @bank_code, account_number: @account_number }
|
971
|
+
else
|
972
|
+
super
|
973
|
+
end
|
974
|
+
end
|
975
|
+
end
|
976
|
+
|
960
977
|
class Rule004301 < BaseRule
|
961
978
|
def converted_details
|
962
979
|
{ bank_code: "66650085", account_number: @account_number }
|
@@ -1028,6 +1045,10 @@ module Ibandit
|
|
1028
1045
|
end
|
1029
1046
|
end
|
1030
1047
|
|
1048
|
+
class Rule004901 < Rule000000
|
1049
|
+
# Rule 0049 01 is actually about modulus checking, not IBAN construction
|
1050
|
+
end
|
1051
|
+
|
1031
1052
|
class Rule005000 < BaseRule
|
1032
1053
|
def converted_details
|
1033
1054
|
{ bank_code: "28550000", account_number: @account_number }
|
data/lib/ibandit/iban.rb
CHANGED
@@ -9,7 +9,8 @@ module Ibandit
|
|
9
9
|
:swift_account_number, :source
|
10
10
|
|
11
11
|
def initialize(argument)
|
12
|
-
|
12
|
+
case argument
|
13
|
+
when String
|
13
14
|
input = argument.to_s.gsub(/\s+/, "").upcase
|
14
15
|
|
15
16
|
pseudo_iban_splitter = PseudoIBANSplitter.new(input)
|
@@ -24,7 +25,7 @@ module Ibandit
|
|
24
25
|
@iban = input
|
25
26
|
extract_swift_details_from_iban!
|
26
27
|
end
|
27
|
-
|
28
|
+
when Hash
|
28
29
|
@source = :local_details
|
29
30
|
build_iban_from_local_details(argument)
|
30
31
|
else
|
@@ -225,7 +226,7 @@ module Ibandit
|
|
225
226
|
return unless valid_country_code?
|
226
227
|
return unless structure[:bban_format]
|
227
228
|
|
228
|
-
if bban
|
229
|
+
if bban&.match?(entire_string_regex(structure[:bban_format]))
|
229
230
|
true
|
230
231
|
else
|
231
232
|
@errors[:format] = Ibandit.translate(:invalid_format,
|
@@ -238,7 +239,9 @@ module Ibandit
|
|
238
239
|
return unless valid_bank_code_length?
|
239
240
|
return true if structure[:bank_code_length]&.zero?
|
240
241
|
|
241
|
-
if swift_bank_code
|
242
|
+
if swift_bank_code&.match?(
|
243
|
+
entire_string_regex(structure[:bank_code_format]),
|
244
|
+
)
|
242
245
|
true
|
243
246
|
else
|
244
247
|
@errors[:bank_code] = Ibandit.translate(:is_invalid)
|
@@ -250,7 +253,9 @@ module Ibandit
|
|
250
253
|
return unless valid_branch_code_length?
|
251
254
|
return true unless structure[:branch_code_format]
|
252
255
|
|
253
|
-
if swift_branch_code
|
256
|
+
if swift_branch_code&.match?(
|
257
|
+
entire_string_regex(structure[:branch_code_format]),
|
258
|
+
)
|
254
259
|
true
|
255
260
|
else
|
256
261
|
@errors[:branch_code] = Ibandit.translate(:is_invalid)
|
@@ -261,7 +266,9 @@ module Ibandit
|
|
261
266
|
def valid_account_number_format?
|
262
267
|
return unless valid_account_number_length?
|
263
268
|
|
264
|
-
if swift_account_number
|
269
|
+
if swift_account_number&.match?(
|
270
|
+
entire_string_regex(structure[:account_number_format]),
|
271
|
+
)
|
265
272
|
true
|
266
273
|
else
|
267
274
|
@errors[:account_number] = Ibandit.translate(:is_invalid)
|
@@ -460,12 +467,12 @@ module Ibandit
|
|
460
467
|
@swift_branch_code = try_dup(local_details[:swift_branch_code])
|
461
468
|
@swift_bank_code = try_dup(local_details[:swift_bank_code])
|
462
469
|
|
463
|
-
@iban
|
470
|
+
@iban = IBANAssembler.assemble(swift_details)
|
464
471
|
|
465
472
|
if source == :pseudo_iban
|
466
|
-
@check_digits
|
473
|
+
@check_digits = try_dup(local_details[:check_digits])
|
467
474
|
else
|
468
|
-
@check_digits
|
475
|
+
@check_digits = @iban.slice(2, 2) unless @iban.nil?
|
469
476
|
end
|
470
477
|
end
|
471
478
|
|
@@ -497,6 +504,10 @@ module Ibandit
|
|
497
504
|
Ibandit.structures[country_code]
|
498
505
|
end
|
499
506
|
|
507
|
+
def entire_string_regex(pattern)
|
508
|
+
Regexp.new("\\A#{pattern}\\z")
|
509
|
+
end
|
510
|
+
|
500
511
|
def formatted
|
501
512
|
iban.to_s.gsub(/(.{4})/, '\1 ').strip
|
502
513
|
end
|
@@ -89,7 +89,9 @@ module Ibandit
|
|
89
89
|
end
|
90
90
|
|
91
91
|
def self.clean_ca_details(local_details)
|
92
|
-
|
92
|
+
account_number = local_details[:account_number].tr("-", "")
|
93
|
+
|
94
|
+
return {} if account_number.length < 7 # minimum length
|
93
95
|
|
94
96
|
bank_code = if local_details[:bank_code].length == 3
|
95
97
|
local_details[:bank_code].rjust(4, "0")
|
@@ -98,7 +100,7 @@ module Ibandit
|
|
98
100
|
end
|
99
101
|
|
100
102
|
{
|
101
|
-
account_number:
|
103
|
+
account_number: account_number.rjust(12, "0"),
|
102
104
|
bank_code: bank_code,
|
103
105
|
}
|
104
106
|
end
|
@@ -198,7 +200,7 @@ module Ibandit
|
|
198
200
|
bank_code, account_number = local_details[:account_number].split("-", 2)
|
199
201
|
elsif local_details[:account_number].gsub(/\s/, "").length == 14
|
200
202
|
cleaned_account_number = local_details[:account_number].gsub(/\s/, "")
|
201
|
-
bank_code
|
203
|
+
bank_code = cleaned_account_number.slice(0, 4)
|
202
204
|
account_number = cleaned_account_number.slice(4, 10)
|
203
205
|
else
|
204
206
|
return {}
|
@@ -512,7 +514,7 @@ module Ibandit
|
|
512
514
|
bank_code = local_details[:bank_code]
|
513
515
|
account_number = local_details[:account_number]
|
514
516
|
else
|
515
|
-
cleaned_acct_number = local_details[:account_number].gsub(
|
517
|
+
cleaned_acct_number = local_details[:account_number].gsub(/\s/, "")
|
516
518
|
|
517
519
|
bank_code = cleaned_acct_number.slice(2, 8)
|
518
520
|
account_number = cleaned_acct_number[10..-1]
|
@@ -573,7 +575,7 @@ module Ibandit
|
|
573
575
|
ken_1 = parts[2].nil? ? "" : parts[2].rjust(6, "0")
|
574
576
|
ken_2 = parts[3].nil? ? "" : parts[3].rjust(4, "0")
|
575
577
|
|
576
|
-
kennitala
|
578
|
+
kennitala = ken_1.empty? ? "" : (ken_1 + ken_2).rjust(10, "0")
|
577
579
|
|
578
580
|
hufo + reikningsnumer + kennitala
|
579
581
|
end
|
data/lib/ibandit/version.rb
CHANGED
@@ -22,15 +22,15 @@
|
|
22
22
|
{ "bank_code": "72020700", "account_number" : "1111111611" }
|
23
23
|
]
|
24
24
|
},
|
25
|
-
{
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
},
|
25
|
+
// {
|
26
|
+
// "convertor": "000300",
|
27
|
+
// "valid": [
|
28
|
+
// { "bank_code": "51010800", "account_number" : "1" }
|
29
|
+
// ],
|
30
|
+
// "invalid": [
|
31
|
+
// { "bank_code": "51010800", "account_number" : "6161604670" }
|
32
|
+
// ]
|
33
|
+
// },
|
34
34
|
{
|
35
35
|
"convertor": "000400",
|
36
36
|
"valid": [
|
@@ -101,12 +101,12 @@
|
|
101
101
|
{"bank_code":"51020000","account_number":"30009963","converted_bank_code":"50020200","converted_account_number":"30009963"}
|
102
102
|
]
|
103
103
|
},
|
104
|
-
{
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
},
|
104
|
+
// {
|
105
|
+
// "convertor": "000900",
|
106
|
+
// "valid": [
|
107
|
+
// {"bank_code":"68351976","account_number":"1116232594","converted_bank_code":"68351557","converted_account_number":"3047232594"}
|
108
|
+
// ]
|
109
|
+
// },
|
110
110
|
{
|
111
111
|
"convertor": "001001",
|
112
112
|
"valid": [
|
@@ -162,9 +162,15 @@
|
|
162
162
|
]
|
163
163
|
},
|
164
164
|
{
|
165
|
-
"convertor": "
|
165
|
+
"convertor": "004901",
|
166
166
|
"valid": [
|
167
|
-
{ "bank_code": "
|
167
|
+
{ "bank_code": "30060010", "account_number": "12345678", "converted_account_number": "12345678" }
|
168
168
|
]
|
169
169
|
}
|
170
|
+
// {
|
171
|
+
// "convertor": "001900",
|
172
|
+
// "valid": [
|
173
|
+
// { "bank_code": "50130100", "account_number": "556", "converted_bank_code": "50120383" }
|
174
|
+
// ]
|
175
|
+
// }
|
170
176
|
]
|
@@ -136,12 +136,12 @@
|
|
136
136
|
{ "bank_code": "10010010", "account_number" : "556", "converted_account_number": "0120440110" }
|
137
137
|
]
|
138
138
|
},
|
139
|
-
{
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
},
|
139
|
+
// {
|
140
|
+
// "convertor": "001900",
|
141
|
+
// "valid": [
|
142
|
+
// { "bank_code": "10010010", "account_number" : "1234567890", "converted_bank_code": "50120383" }
|
143
|
+
// ]
|
144
|
+
// },
|
145
145
|
{
|
146
146
|
"convertor": "002002",
|
147
147
|
"valid": [
|
@@ -318,6 +318,20 @@
|
|
318
318
|
{ "bank_code": "10010010", "account_number" : "0040400000" },
|
319
319
|
{ "bank_code": "10010010", "account_number" : "0040412000" }
|
320
320
|
]
|
321
|
+
},
|
322
|
+
{
|
323
|
+
"convertor": "004201",
|
324
|
+
"valid": [
|
325
|
+
{ "bank_code": "10010010", "account_number" : "0050462000" },
|
326
|
+
{ "bank_code": "70020001", "account_number" : "0040402000" },
|
327
|
+
{ "bank_code": "70020001", "account_number" : "1004400001" }
|
328
|
+
],
|
329
|
+
"invalid": [
|
330
|
+
{ "bank_code": "10010010", "account_number" : "504620001" },
|
331
|
+
{ "bank_code": "10010010", "account_number" : "0040400000" },
|
332
|
+
{ "bank_code": "10010010", "account_number" : "0040412000" },
|
333
|
+
{ "bank_code": "70020001", "account_number" : "1035400001" }
|
334
|
+
]
|
321
335
|
},
|
322
336
|
{
|
323
337
|
"convertor": "004301",
|
@@ -421,5 +435,16 @@
|
|
421
435
|
"valid": [
|
422
436
|
{ "bank_code": "10010010", "account_number" : "1234567890", "converted_bank_code": "66010200" }
|
423
437
|
]
|
438
|
+
},
|
439
|
+
{
|
440
|
+
"convertor": "004901",
|
441
|
+
"valid": [
|
442
|
+
{
|
443
|
+
"bank_code": "30060010",
|
444
|
+
"account_number": "1234567890",
|
445
|
+
"converted_bank_code": "30060010",
|
446
|
+
"converted_account_number": "1234567890"
|
447
|
+
}
|
448
|
+
]
|
424
449
|
}
|
425
450
|
]
|
data/spec/ibandit/iban_spec.rb
CHANGED
@@ -112,6 +112,22 @@ describe Ibandit::IBAN do
|
|
112
112
|
its(:local_check_digits) { is_expected.to be_nil }
|
113
113
|
end
|
114
114
|
|
115
|
+
context "when the IBAN was created from a Belgian IBAN" do
|
116
|
+
let(:iban_code) { "BE62510007547061" }
|
117
|
+
|
118
|
+
its(:country_code) { is_expected.to eq("BE") }
|
119
|
+
its(:bank_code) { is_expected.to eq("510") }
|
120
|
+
its(:branch_code) { is_expected.to be_nil }
|
121
|
+
its(:account_number) { is_expected.to eq("510007547061") }
|
122
|
+
its(:account_number_suffix) { is_expected.to be_nil }
|
123
|
+
its(:swift_bank_code) { is_expected.to eq("510") }
|
124
|
+
its(:swift_branch_code) { is_expected.to be_nil }
|
125
|
+
its(:swift_account_number) { is_expected.to eq("510007547061") }
|
126
|
+
its(:swift_national_id) { is_expected.to eq("510") }
|
127
|
+
its(:local_check_digits) { is_expected.to eq("61") }
|
128
|
+
its(:bban) { is_expected.to eq("510007547061") }
|
129
|
+
end
|
130
|
+
|
115
131
|
context "when the IBAN was created with local details" do
|
116
132
|
let(:arg) do
|
117
133
|
{
|
@@ -452,6 +468,13 @@ describe Ibandit::IBAN do
|
|
452
468
|
its(:to_s) { is_expected.to eq("") }
|
453
469
|
end
|
454
470
|
|
471
|
+
context "and account number has invalid characters in" do
|
472
|
+
let(:account_number) { "123456XX789" }
|
473
|
+
let(:bank_code) { "0036" }
|
474
|
+
|
475
|
+
its(:valid?) { is_expected.to be false }
|
476
|
+
end
|
477
|
+
|
455
478
|
context "and a 12 digit account number" do
|
456
479
|
let(:account_number) { "012345678900" }
|
457
480
|
let(:bank_code) { "0036" }
|
@@ -2247,16 +2270,16 @@ describe Ibandit::IBAN do
|
|
2247
2270
|
|
2248
2271
|
context "with an invalid branch code" do
|
2249
2272
|
let(:iban_code) { "GB60BARC20000055779911" }
|
2273
|
+
let(:valid_bank_code) { true }
|
2274
|
+
let(:valid_branch_code) { false }
|
2275
|
+
let(:valid_account_number) { true }
|
2276
|
+
|
2250
2277
|
before { Ibandit.bic_finder = double(call: "BARCGB22XXX") }
|
2251
2278
|
|
2252
2279
|
after { Ibandit.bic_finder = nil }
|
2253
2280
|
|
2254
2281
|
before { iban.valid_local_modulus_check? }
|
2255
2282
|
|
2256
|
-
let(:valid_bank_code) { true }
|
2257
|
-
let(:valid_branch_code) { false }
|
2258
|
-
let(:valid_account_number) { true }
|
2259
|
-
|
2260
2283
|
it "calls valid_branch_code? with an IBAN object" do
|
2261
2284
|
expect(Ibandit.modulus_checker).
|
2262
2285
|
to receive(:valid_branch_code?).
|
@@ -167,6 +167,12 @@ describe Ibandit::LocalDetailsCleaner do
|
|
167
167
|
its([:country_code]) { is_expected.to eq(country_code) }
|
168
168
|
its([:bank_code]) { is_expected.to eq("0036") }
|
169
169
|
its([:branch_code]) { is_expected.to eq("00063") }
|
170
|
+
|
171
|
+
context "with a hyphen" do
|
172
|
+
let(:account_number) { "0123456-789" }
|
173
|
+
|
174
|
+
its([:account_number]) { is_expected.to eq("000123456789") }
|
175
|
+
end
|
170
176
|
end
|
171
177
|
|
172
178
|
context "Cyprus" do
|
@@ -286,7 +292,7 @@ describe Ibandit::LocalDetailsCleaner do
|
|
286
292
|
|
287
293
|
context "with unsupported account details" do
|
288
294
|
let(:account_number) { "7955791111" }
|
289
|
-
let(:bank_code) { "
|
295
|
+
let(:bank_code) { "99999999" }
|
290
296
|
|
291
297
|
it { is_expected.to eq(local_details_with_swift) }
|
292
298
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
5
|
describe Ibandit::PseudoIBANAssembler do
|
6
|
-
subject(:pseudo_iban) { described_class.new(local_details).assemble }
|
6
|
+
subject(:pseudo_iban) { described_class.new(**local_details).assemble }
|
7
7
|
|
8
8
|
context "for Sweden" do
|
9
9
|
context "with valid parameters" do
|
@@ -9,7 +9,7 @@ describe "structures.yml" do
|
|
9
9
|
structures.each do |country, rules|
|
10
10
|
context country do
|
11
11
|
rules.each do |rule, value|
|
12
|
-
next unless rule
|
12
|
+
next unless rule.to_s.end_with?("_format")
|
13
13
|
|
14
14
|
it "builds #{rule} rule" do
|
15
15
|
expect { Regexp.new(value) }.to_not raise_exception
|