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 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.