ibandit 0.11.25 → 0.11.26

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 25eea6c456d9782856e5600061dc8414d90f651a
4
- data.tar.gz: c81156af68d0817c88dd9faad9a908a7a75bab2d
3
+ metadata.gz: 73a5ffec9e66a0ebf5dccf613bedb5e0da311444
4
+ data.tar.gz: a6d3de9434b4b87e3df2b9a6a4e6c841331b949c
5
5
  SHA512:
6
- metadata.gz: 343b1bf9e56d78bc6ee805e75d260f20596770d3ff7b9ce6107579cad1dee21d9cbdec714fa7b7c0c4fd59f2facd8ab5e290ccfe4238cba82fca014f321b3511
7
- data.tar.gz: 45ddb672d2b7db64b3c2dec6bceb6e3b87be62dda0cca036b0f55d77f9e9756e6ad454fd257ab3610d98d1de9206786fb31022816dae13fa61e2e97ad491ec95
6
+ metadata.gz: ce3d098232431f5d49b2c533afe6eac7ca260cabfcda9add4ff4cc2b3b0a3bb1bae8d98e3a0bfda1416d5ea0c96533bb9b31b38ab4f5cc06800a49e93d7f19f0
7
+ data.tar.gz: 6612b734b2bad0b49af6d2460b4536a26bea154ed81011c654c02202c68bc3d34db4b290dc1731831c0b77480202dc7f32c88bb86f507894a3bc3d23f9b4ddae
@@ -1,3 +1,7 @@
1
+ ## 0.11.26 - January 30, 2019
2
+
3
+ - Add support for US pseudo-IBANs
4
+
1
5
  ## 0.11.25 - January 10, 2019
2
6
 
3
7
  - Prevent account numbers from being all-zero in Australia
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
@@ -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
@@ -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 = (
@@ -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", "LV", "NL", "RO", "SI", "SK"
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
@@ -1,3 +1,3 @@
1
1
  module Ibandit
2
- VERSION = "0.11.25".freeze
2
+ VERSION = "0.11.26".freeze
3
3
  end
@@ -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.25
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 00:00:00.000000000 Z
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.6.14
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.