ibandit 0.11.25 → 0.11.26
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +16 -0
- data/data/structures.yml +11 -0
- data/lib/ibandit/constants.rb +2 -1
- data/lib/ibandit/iban.rb +19 -0
- data/lib/ibandit/local_details_cleaner.rb +14 -1
- data/lib/ibandit/version.rb +1 -1
- data/spec/ibandit/iban_spec.rb +132 -0
- data/spec/ibandit/local_details_cleaner_spec.rb +20 -0
- data/spec/ibandit/pseudo_iban_assembler_spec.rb +36 -0
- data/spec/ibandit/pseudo_iban_splitter_spec.rb +24 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73a5ffec9e66a0ebf5dccf613bedb5e0da311444
|
4
|
+
data.tar.gz: a6d3de9434b4b87e3df2b9a6a4e6c841331b949c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce3d098232431f5d49b2c533afe6eac7ca260cabfcda9add4ff4cc2b3b0a3bb1bae8d98e3a0bfda1416d5ea0c96533bb9b31b38ab4f5cc06800a49e93d7f19f0
|
7
|
+
data.tar.gz: 6612b734b2bad0b49af6d2460b4536a26bea154ed81011c654c02202c68bc3d34db4b290dc1731831c0b77480202dc7f32c88bb86f507894a3bc3d23f9b4ddae
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -57,6 +57,7 @@ For example:
|
|
57
57
|
| Spain | :white_check_mark: | :white_check_mark: | |
|
58
58
|
| Sweden | :white_check_mark: | | :white_check_mark: |
|
59
59
|
| United Kingdom | :white_check_mark: | :white_check_mark: | |
|
60
|
+
| USA | | | :white_check_mark: |
|
60
61
|
|
61
62
|
## Usage
|
62
63
|
|
@@ -561,6 +562,21 @@ iban.country_code # => "NZ"
|
|
561
562
|
iban.bank_code # => "01"
|
562
563
|
iban.branch_code # => "0004"
|
563
564
|
iban.account_number # => "3333333044"
|
565
|
+
|
566
|
+
# USA
|
567
|
+
iban = Ibandit::IBAN.new(
|
568
|
+
country_code: 'US',
|
569
|
+
bank_code: '965498456', # 9-digit routing number
|
570
|
+
account_number: '0123456789' # 1 to 17 digits
|
571
|
+
)
|
572
|
+
iban.pseudo_iban # => "USZZ965498456_______0123456789"
|
573
|
+
iban.iban # => nil
|
574
|
+
|
575
|
+
iban = Ibandit::IBAN.new('USZZ965498456_______0123456789')
|
576
|
+
iban.country_code # => "US"
|
577
|
+
iban.bank_code # => "965498456"
|
578
|
+
iban.account_number # => "_______0123456789"
|
579
|
+
iban.iban # => nil
|
564
580
|
```
|
565
581
|
|
566
582
|
## Other libraries
|
data/data/structures.yml
CHANGED
@@ -897,3 +897,14 @@ CA:
|
|
897
897
|
:pseudo_iban_bank_code_length: 4
|
898
898
|
:pseudo_iban_branch_code_length: 5
|
899
899
|
:pseudo_iban_account_number_length: 12
|
900
|
+
US:
|
901
|
+
:bank_code_length: 9
|
902
|
+
:branch_code_length: 0
|
903
|
+
:account_number_length: 17
|
904
|
+
:bank_code_format: "\\d{9}"
|
905
|
+
# TODO: update account number format based on inputs from user research
|
906
|
+
:account_number_format: ".{1,17}"
|
907
|
+
:national_id_length: 9
|
908
|
+
:pseudo_iban_bank_code_length: 9
|
909
|
+
:pseudo_iban_branch_code_length: 0
|
910
|
+
:pseudo_iban_account_number_length: 17
|
data/lib/ibandit/constants.rb
CHANGED
@@ -4,7 +4,7 @@ module Ibandit
|
|
4
4
|
HR HU IE IS IT LT LU LV MC MT NL NO PL
|
5
5
|
PT RO SE SI SK SM].freeze
|
6
6
|
|
7
|
-
PSEUDO_IBAN_COUNTRY_CODES = %w[AU SE NZ CA].freeze
|
7
|
+
PSEUDO_IBAN_COUNTRY_CODES = %w[AU SE NZ CA US].freeze
|
8
8
|
DECONSTRUCTABLE_IBAN_COUNTRY_CODES =
|
9
9
|
CONSTRUCTABLE_IBAN_COUNTRY_CODES - PSEUDO_IBAN_COUNTRY_CODES
|
10
10
|
|
@@ -15,6 +15,7 @@ module Ibandit
|
|
15
15
|
"AU" => "_", # Using _ because AU account numbers are alphanumeric
|
16
16
|
"NZ" => "_",
|
17
17
|
"CA" => "_",
|
18
|
+
"US" => "_",
|
18
19
|
}.freeze
|
19
20
|
|
20
21
|
SUPPORTED_COUNTRY_CODES = (
|
data/lib/ibandit/iban.rb
CHANGED
@@ -284,6 +284,7 @@ module Ibandit
|
|
284
284
|
when "AU" then valid_australian_details?
|
285
285
|
when "NZ" then valid_nz_details?
|
286
286
|
when "CA" then valid_ca_details?
|
287
|
+
when "US" then bank_code_passes_checksum_test?
|
287
288
|
else true
|
288
289
|
end
|
289
290
|
end
|
@@ -383,6 +384,24 @@ module Ibandit
|
|
383
384
|
valid_modulus_check_branch_code?
|
384
385
|
end
|
385
386
|
|
387
|
+
# rubocop:disable Metrics/AbcSize
|
388
|
+
def bank_code_passes_checksum_test?
|
389
|
+
return false if swift_bank_code.length != 9
|
390
|
+
|
391
|
+
code_digits = swift_bank_code.chars.map(&:to_i)
|
392
|
+
mod =
|
393
|
+
(
|
394
|
+
3 * (code_digits[0] + code_digits[3] + code_digits[6]) +
|
395
|
+
7 * (code_digits[1] + code_digits[4] + code_digits[7]) +
|
396
|
+
1 * (code_digits[2] + code_digits[5] + code_digits[8])
|
397
|
+
) % 10
|
398
|
+
|
399
|
+
@errors[:bank_code] = Ibandit.translate(:is_invalid) unless mod.zero?
|
400
|
+
|
401
|
+
mod.zero?
|
402
|
+
end
|
403
|
+
# rubocop:enable Metrics/AbcSize
|
404
|
+
|
386
405
|
###################
|
387
406
|
# Private methods #
|
388
407
|
###################
|
@@ -32,7 +32,8 @@ module Ibandit
|
|
32
32
|
|
33
33
|
def self.required_fields(country_code)
|
34
34
|
case country_code
|
35
|
-
when "AT", "CY", "DE", "FI", "LT", "LU",
|
35
|
+
when "AT", "CY", "DE", "FI", "LT", "LU",
|
36
|
+
"LV", "NL", "RO", "SI", "SK", "US"
|
36
37
|
%i[bank_code account_number]
|
37
38
|
when "BE", "CZ", "DK", "EE", "ES", "HR",
|
38
39
|
"HU", "IS", "NO", "PL", "SE", "NZ"
|
@@ -99,6 +100,18 @@ module Ibandit
|
|
99
100
|
}
|
100
101
|
end
|
101
102
|
|
103
|
+
def self.clean_us_details(local_details)
|
104
|
+
return {} unless local_details[:bank_code].length == 9
|
105
|
+
|
106
|
+
account_number = local_details[:account_number].delete(" ")
|
107
|
+
return {} unless (1..17).cover?(account_number.length)
|
108
|
+
|
109
|
+
{
|
110
|
+
bank_code: local_details[:bank_code],
|
111
|
+
account_number: account_number.rjust(17, "_"),
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
102
115
|
def self.clean_bg_details(local_details)
|
103
116
|
# Bulgarian national bank details were replaced with IBANs in 2006.
|
104
117
|
local_details
|
data/lib/ibandit/version.rb
CHANGED
data/spec/ibandit/iban_spec.rb
CHANGED
@@ -601,6 +601,138 @@ describe Ibandit::IBAN do
|
|
601
601
|
to eq(account_number: "is the wrong length (should be 10 characters)")
|
602
602
|
end
|
603
603
|
end
|
604
|
+
|
605
|
+
context "when the IBAN was created with local details for US" do
|
606
|
+
let(:arg) do
|
607
|
+
{
|
608
|
+
country_code: "US",
|
609
|
+
bank_code: bank_code,
|
610
|
+
account_number: account_number,
|
611
|
+
}
|
612
|
+
end
|
613
|
+
|
614
|
+
context "and a 9 digit bank code" do
|
615
|
+
let(:bank_code) { "965498456" }
|
616
|
+
let(:account_number) { "01234567890123456" }
|
617
|
+
|
618
|
+
its(:country_code) { is_expected.to eq("US") }
|
619
|
+
its(:bank_code) { is_expected.to eq(bank_code) }
|
620
|
+
its(:account_number) { is_expected.to eq(account_number) }
|
621
|
+
its(:swift_bank_code) { is_expected.to eq(bank_code) }
|
622
|
+
its(:swift_branch_code) { is_expected.to eq(nil) }
|
623
|
+
its(:swift_account_number) { is_expected.to eq(account_number) }
|
624
|
+
its(:swift_national_id) { is_expected.to eq(bank_code) }
|
625
|
+
its(:pseudo_iban) do
|
626
|
+
is_expected.to eq("USZZ96549845601234567890123456")
|
627
|
+
end
|
628
|
+
|
629
|
+
its(:iban) { is_expected.to be_nil }
|
630
|
+
its(:valid?) { is_expected.to eq(true) }
|
631
|
+
its(:to_s) { is_expected.to eq("") }
|
632
|
+
end
|
633
|
+
|
634
|
+
context "and a 7 digit bank code" do
|
635
|
+
let(:bank_code) { "0123456" }
|
636
|
+
let(:account_number) { "01234567890123456" }
|
637
|
+
|
638
|
+
its(:country_code) { is_expected.to eq("US") }
|
639
|
+
its(:bank_code) { is_expected.to eq(bank_code) }
|
640
|
+
its(:account_number) { is_expected.to eq(account_number) }
|
641
|
+
its(:swift_bank_code) { is_expected.to eq(bank_code) }
|
642
|
+
its(:swift_branch_code) { is_expected.to eq(nil) }
|
643
|
+
its(:swift_account_number) { is_expected.to eq(account_number) }
|
644
|
+
its(:swift_national_id) { is_expected.to eq(bank_code) }
|
645
|
+
its(:pseudo_iban) do
|
646
|
+
is_expected.to eq("USZZ__012345601234567890123456")
|
647
|
+
end
|
648
|
+
|
649
|
+
its(:iban) { is_expected.to be_nil }
|
650
|
+
its(:valid?) { is_expected.to eq(false) }
|
651
|
+
its(:to_s) { is_expected.to eq("") }
|
652
|
+
end
|
653
|
+
|
654
|
+
context "and bank code that doesn't pass checksum test" do
|
655
|
+
let(:bank_code) { "900000000" }
|
656
|
+
let(:account_number) { "01234567890123456" }
|
657
|
+
|
658
|
+
its(:iban) { is_expected.to be_nil }
|
659
|
+
|
660
|
+
it "returns an error on bank_code attribute" do
|
661
|
+
expect(subject.valid?).to eq(false)
|
662
|
+
expect(subject.errors).to eq(bank_code: "is invalid")
|
663
|
+
end
|
664
|
+
end
|
665
|
+
|
666
|
+
context "and a 7 digit account number" do
|
667
|
+
let(:account_number) { "0123456" }
|
668
|
+
let(:bank_code) { "965498456" }
|
669
|
+
|
670
|
+
its(:country_code) { is_expected.to eq("US") }
|
671
|
+
its(:bank_code) { is_expected.to eq(bank_code) }
|
672
|
+
its(:account_number) { is_expected.to eq("__________0123456") }
|
673
|
+
its(:swift_bank_code) { is_expected.to eq(bank_code) }
|
674
|
+
its(:swift_branch_code) { is_expected.to eq(nil) }
|
675
|
+
its(:swift_account_number) { is_expected.to eq("__________0123456") }
|
676
|
+
its(:swift_national_id) { is_expected.to eq(bank_code) }
|
677
|
+
its(:pseudo_iban) do
|
678
|
+
is_expected.to eq("USZZ965498456__________0123456")
|
679
|
+
end
|
680
|
+
|
681
|
+
its(:iban) { is_expected.to be_nil }
|
682
|
+
its(:valid?) { is_expected.to eq(true) }
|
683
|
+
its(:to_s) { is_expected.to eq("") }
|
684
|
+
end
|
685
|
+
|
686
|
+
context "and a 17 digit account number" do
|
687
|
+
let(:account_number) { "01234567890123456" }
|
688
|
+
let(:bank_code) { "965498456" }
|
689
|
+
|
690
|
+
its(:country_code) { is_expected.to eq("US") }
|
691
|
+
its(:bank_code) { is_expected.to eq(bank_code) }
|
692
|
+
its(:account_number) { is_expected.to eq("01234567890123456") }
|
693
|
+
its(:swift_bank_code) { is_expected.to eq(bank_code) }
|
694
|
+
its(:swift_branch_code) { is_expected.to eq(nil) }
|
695
|
+
its(:swift_account_number) { is_expected.to eq(account_number) }
|
696
|
+
its(:swift_national_id) { is_expected.to eq(bank_code) }
|
697
|
+
its(:pseudo_iban) do
|
698
|
+
is_expected.to eq("USZZ96549845601234567890123456")
|
699
|
+
end
|
700
|
+
|
701
|
+
its(:iban) { is_expected.to be_nil }
|
702
|
+
its(:valid?) { is_expected.to be true }
|
703
|
+
its(:to_s) { is_expected.to eq("") }
|
704
|
+
end
|
705
|
+
end
|
706
|
+
|
707
|
+
context "when the IBAN was created from a US pseudo-IBAN" do
|
708
|
+
let(:arg) { "USZZ96549845601234567890123456" }
|
709
|
+
|
710
|
+
its(:country_code) { is_expected.to eq("US") }
|
711
|
+
its(:bank_code) { is_expected.to eq("965498456") }
|
712
|
+
its(:branch_code) { is_expected.to be_nil }
|
713
|
+
its(:account_number) { is_expected.to eq("01234567890123456") }
|
714
|
+
its(:swift_bank_code) { is_expected.to eq("965498456") }
|
715
|
+
its(:swift_branch_code) { is_expected.to eq(nil) }
|
716
|
+
its(:swift_account_number) { is_expected.to eq("01234567890123456") }
|
717
|
+
its(:swift_national_id) { is_expected.to eq("965498456") }
|
718
|
+
its(:pseudo_iban) do
|
719
|
+
is_expected.to eq("USZZ96549845601234567890123456")
|
720
|
+
end
|
721
|
+
|
722
|
+
its(:iban) { is_expected.to be_nil }
|
723
|
+
its(:valid?) { is_expected.to be true }
|
724
|
+
its(:to_s) { is_expected.to eq("") }
|
725
|
+
end
|
726
|
+
|
727
|
+
context "when the input is an invalid US pseudo-IBAN" do
|
728
|
+
let(:arg) { "USZZ__012345601234567890123456" }
|
729
|
+
|
730
|
+
it "is invalid and has the correct errors" do
|
731
|
+
expect(subject.valid?).to eq(false)
|
732
|
+
expect(subject.errors).
|
733
|
+
to eq(bank_code: "is the wrong length (should be 9 characters)")
|
734
|
+
end
|
735
|
+
end
|
604
736
|
end
|
605
737
|
|
606
738
|
describe "#to_s" do
|
@@ -1158,4 +1158,24 @@ describe Ibandit::LocalDetailsCleaner do
|
|
1158
1158
|
it { is_expected.to eq(local_details_with_swift) }
|
1159
1159
|
end
|
1160
1160
|
end
|
1161
|
+
|
1162
|
+
context "US" do
|
1163
|
+
context "when the account number has space characters" do
|
1164
|
+
let(:country_code) { "US" }
|
1165
|
+
let(:bank_code) { "012345678" }
|
1166
|
+
let(:account_number) { "0123-45678 1234567" }
|
1167
|
+
|
1168
|
+
its([:bank_code]) { is_expected.to eq(bank_code) }
|
1169
|
+
its([:account_number]) { is_expected.to eq("0123-456781234567") }
|
1170
|
+
end
|
1171
|
+
|
1172
|
+
context "when the account number is shorter than the maximum length" do
|
1173
|
+
let(:country_code) { "US" }
|
1174
|
+
let(:bank_code) { "012345678" }
|
1175
|
+
let(:account_number) { "0123456789" }
|
1176
|
+
|
1177
|
+
its([:bank_code]) { is_expected.to eq(bank_code) }
|
1178
|
+
its([:account_number]) { is_expected.to eq("_______0123456789") }
|
1179
|
+
end
|
1180
|
+
end
|
1161
1181
|
end
|
@@ -189,6 +189,42 @@ describe Ibandit::PseudoIBANAssembler do
|
|
189
189
|
end
|
190
190
|
end
|
191
191
|
|
192
|
+
context "for US" do
|
193
|
+
context "with valid parameters" do
|
194
|
+
let(:local_details) do
|
195
|
+
{
|
196
|
+
country_code: "US",
|
197
|
+
bank_code: "012345678",
|
198
|
+
account_number: "01234567890123456",
|
199
|
+
}
|
200
|
+
end
|
201
|
+
|
202
|
+
it { is_expected.to eq("USZZ01234567801234567890123456") }
|
203
|
+
end
|
204
|
+
|
205
|
+
context "without a bank_code" do
|
206
|
+
let(:local_details) do
|
207
|
+
{
|
208
|
+
country_code: "US",
|
209
|
+
account_number: "01234567890123456",
|
210
|
+
}
|
211
|
+
end
|
212
|
+
|
213
|
+
it { is_expected.to be_nil }
|
214
|
+
end
|
215
|
+
|
216
|
+
context "without an account number" do
|
217
|
+
let(:local_details) do
|
218
|
+
{
|
219
|
+
country_code: "US",
|
220
|
+
bank_code: "012345678",
|
221
|
+
}
|
222
|
+
end
|
223
|
+
|
224
|
+
it { is_expected.to be_nil }
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
192
228
|
context "for a country that does not have pseudo-IBANs" do
|
193
229
|
let(:local_details) do
|
194
230
|
{
|
@@ -95,5 +95,29 @@ describe Ibandit::PseudoIBANSplitter do
|
|
95
95
|
its([:branch_code]) { is_expected.to eq("00063") }
|
96
96
|
its([:account_number]) { is_expected.to eq("012345678900") }
|
97
97
|
end
|
98
|
+
|
99
|
+
context "for a US pseudo-IBAN without padding" do
|
100
|
+
let(:pseudo_iban) { "USZZ0123456780123456" }
|
101
|
+
|
102
|
+
its([:country_code]) { is_expected.to eq("US") }
|
103
|
+
its([:bank_code]) { is_expected.to eq("012345678") }
|
104
|
+
its([:account_number]) { is_expected.to eq("0123456") }
|
105
|
+
end
|
106
|
+
|
107
|
+
context "for a US pseudo-IBAN with padding" do
|
108
|
+
let(:pseudo_iban) { "USZZ012345678__________0123456" }
|
109
|
+
|
110
|
+
its([:country_code]) { is_expected.to eq("US") }
|
111
|
+
its([:bank_code]) { is_expected.to eq("012345678") }
|
112
|
+
its([:account_number]) { is_expected.to eq("0123456") }
|
113
|
+
end
|
114
|
+
|
115
|
+
context "for a US pseudo-IBAN with a 17-digit account number" do
|
116
|
+
let(:pseudo_iban) { "USZZ01234567801234567890123456" }
|
117
|
+
|
118
|
+
its([:country_code]) { is_expected.to eq("US") }
|
119
|
+
its([:bank_code]) { is_expected.to eq("012345678") }
|
120
|
+
its([:account_number]) { is_expected.to eq("01234567890123456") }
|
121
|
+
end
|
98
122
|
end
|
99
123
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ibandit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.26
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GoCardless
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -210,7 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
210
210
|
version: '0'
|
211
211
|
requirements: []
|
212
212
|
rubyforge_project:
|
213
|
-
rubygems_version: 2.
|
213
|
+
rubygems_version: 2.5.2.3
|
214
214
|
signing_key:
|
215
215
|
specification_version: 4
|
216
216
|
summary: Convert national banking details into IBANs, and vice-versa.
|