ibandit 1.12.0 → 1.14.0

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
  SHA256:
3
- metadata.gz: 1f0083e6ead39b150f21564cf99eed6dd2af43f1116127a95ac4a8ba020c5e37
4
- data.tar.gz: 79858e3247d419d61154b6f99274c44664255ee814edaffb4a08a8a4d9dc4346
3
+ metadata.gz: a67c31f07d7b33b4f60998d4e4fd97473c72c36f23817bb07e5d1d632fa7aba9
4
+ data.tar.gz: 680db335cd4e6697c45f42550145ed5cce83262ab83eb6abb0d929579cfb00fb
5
5
  SHA512:
6
- metadata.gz: 5ad2acab721cce23b63c9c84a6126001df08b3f4205ba57ea63a90bbcd4649a0af2f251b871933a08a755e5a9c6df11f582b8e8dcea6520089c26d4cf1c285ea
7
- data.tar.gz: 30c4e57ec85de9bf28433a811e5c08b2ca3a83f4fa0dcce714526a2a9afce03da39298c732a6e7269106d430d1c26ae9777869dfb1d843ffbb202a8558b46261
6
+ metadata.gz: 5498e32bae4a3779c2a5965d3b71c375ee823582803bbf2e78a7667476cbd7af6be0b7bbdd101a14bd678bd262653e14f481a52cbe8a65a728a10e0916441557
7
+ data.tar.gz: 8d4314276d23c4cc338d9b31d634a48fef8ad4c4c3aface176d99361550a9dbf15a83429ed90fc22aacec48dd5f3ac20dcf12af675535d97d52fe3453ba3f4b5
@@ -7,7 +7,7 @@ jobs:
7
7
  validate:
8
8
  strategy:
9
9
  matrix:
10
- ruby-version: [2.6, 2.7, 3.0, 3.1]
10
+ ruby-version: ["2.6", "2.7", "3.0", "3.1", "3.2"]
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
13
  - uses: actions/checkout@v3
data/.rubocop.yml CHANGED
@@ -4,7 +4,7 @@ inherit_gem:
4
4
  require: rubocop-rails
5
5
 
6
6
  AllCops:
7
- TargetRubyVersion: 2.5
7
+ TargetRubyVersion: 3.2
8
8
 
9
9
  # Limit lines to 90 characters.
10
10
  Layout/LineLength:
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.1.0
1
+ 3.2.1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 1.14.0 - March 28, 2023
2
+
3
+ - Update IBAN registry #233
4
+ - Add GL and FO to the IBAN constructor for local details
5
+
6
+ ## 1.13.0 - March 6, 2023
7
+
8
+ - Update BLZ data - BLZ_20230306
9
+
1
10
  ## 1.12.0 - December 5, 2022
2
11
 
3
12
  - Update BLZ data - BLZ_20221205
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ # rubocop:disable Layout/LineLength
5
+
4
6
  # Script for parsing the IBAN registry (IBAN_Registry.txt) and IBAN structures
5
7
  # (IBANSTRUCTURE.xml) files from SWIFT.
6
8
  require "csv"
@@ -22,143 +24,240 @@ end
22
24
 
23
25
  class Report
24
26
  include SAXMachine
25
- elements "ibanstructure", as: :countries, class: Country
27
+ elements "ibanstructure_v2", as: :countries, class: Country
26
28
  end
27
29
 
28
- # rubocop:disable Metrics/AbcSize
29
- def get_iban_structures(iban_structures_file, iban_registry_file)
30
- bban_formats = get_bban_formats(iban_registry_file)
31
-
32
- report = Report.parse(iban_structures_file)
33
- report.countries.each_with_object({}) do |country, hash|
34
- hash[country.country_code] = {
35
- bank_code_position: country.bank_code_position.to_i,
36
- bank_code_length: country.bank_code_length.to_i,
37
- branch_code_position: country.branch_code_position.to_i,
38
- branch_code_length: country.branch_code_length.to_i,
39
- account_number_position: country.account_number_position.to_i,
40
- account_number_length: country.account_number_length.to_i,
41
- total_length: country.total_length.to_i,
42
- national_id_length: country.national_id_length.to_i,
43
- }.merge(bban_formats[country.country_code])
30
+ class IbanRegistryTextFile
31
+ attr_accessor :lines, :registry
32
+
33
+ FILE_ELEMENTS = [
34
+ # 0 Data element
35
+ # 1 Name of country
36
+ # 2 IBAN prefix country code (ISO 3166)
37
+ COUNTRY_CODE = 2,
38
+ # 3 Country code includes other countries/territories
39
+ # 4 SEPA country
40
+ # 5 SEPA country also includes
41
+ # 6 Domestic account number example
42
+ DOMESTIC_ACCOUNT_NUMBER_EXAMPLE = 6,
43
+ # 7 BBAN
44
+ # 8 BBAN structure
45
+ BBAN_STRUCTURE = 8,
46
+ # 9 BBAN length
47
+ # 10 Bank identifier position within the BBAN
48
+ BANK_IDENTIFIER_POSITION = 10,
49
+ # 11 Bank identifier pattern
50
+ BANK_IDENTIFIER_PATTERN = 11,
51
+ # 12 Branch identifier position within the BBAN
52
+ BRANCH_IDENTIFIER_POSITION = 12,
53
+ # 13 Branch identifier pattern
54
+ BRANCH_IDENTIFIER_PATTERN = 13,
55
+ # 14 Bank identifier example
56
+ # 15 Branch identifier example
57
+ # 16 BBAN example
58
+ BBAN_EXAMPLE = 16,
59
+ # 17 IBAN
60
+ # 18 IBAN structure
61
+ # 19 IBAN length
62
+ # 20 Effective date
63
+ # 21 IBAN electronic format example
64
+ IBAN_EXAMPLE = 21,
65
+ ].freeze
66
+
67
+ def self.call(path = "../data/raw/IBAN_Registry.txt")
68
+ lines = CSV.read(
69
+ File.expand_path(path, __dir__),
70
+ col_sep: "\t",
71
+ headers: true,
72
+ encoding: Encoding::ISO_8859_1,
73
+ ).to_a.transpose.tap(&:shift)
74
+
75
+ new(lines).tap(&:parse)
44
76
  end
45
- end
46
- # rubocop:enable Metrics/AbcSize
47
-
48
- FILE_ELEMENTS = [
49
- # 0 Data element
50
- # 1 Name of country
51
- # 2 IBAN prefix country code (ISO 3166)
52
- COUNTRY_CODE = 2,
53
- # 3 Country code includes other countries/territories
54
- # 4 SEPA country
55
- # 5 SEPA country also includes
56
- # 6 Domestic account number example
57
- # 7 BBAN
58
- # 8 BBAN structure
59
- BBAN_STRUCTURE = 8,
60
- # 9 BBAN length
61
- # 10 Bank identifier position within the BBAN
62
- # 11 Bank identifier pattern
63
- BANK_IDENTIFIER_PATTERN = 11,
64
- # 12 Branch identifier position within the BBAN
65
- # 13 Branch identifier pattern
66
- BRANCH_IDENTIFIER_PATTERN = 13,
67
- # 14 Bank identifier example
68
- # 15 Branch identifier example
69
- # 16 BBAN example
70
- # 17 IBAN
71
- # 18 IBAN structure
72
- # 19 IBAN length
73
- # 20 Effective date
74
- # 21 IBAN electronic format example
75
- ].freeze
76
-
77
- def get_bban_formats(iban_registry_file)
78
- iban_registry_file.each_with_object({}) do |line, hash|
79
- bban_structure = line[BBAN_STRUCTURE].strip
80
-
81
- bank_code_structure = line[BANK_IDENTIFIER_PATTERN].strip
82
- branch_code_structure = line[BRANCH_IDENTIFIER_PATTERN]&.strip
83
-
84
- bank_code_structure = "" if bank_code_structure == "N/A"
85
-
86
- country_code = line[COUNTRY_CODE].strip
87
- hash[country_code] = convert_swift_convention(bban_structure,
88
- bank_code_structure,
89
- branch_code_structure)
77
+
78
+ def initialize(lines)
79
+ @lines = lines
80
+ @registry = {}
90
81
  end
91
- end
92
82
 
93
- # IBAN Registry has BBAN format (which seems to be accurate), and Bank
94
- # identifier length, which contains something roughly like the format for the
95
- # bank code and usually the branch code where applicable. This is a best attempt
96
- # to convert those from weird SWIFT-talk into regexes, and then work out the
97
- # account number format regex by taking the bank and branch code regexes off
98
- # the front of the BBAN format.
99
- #
100
- # This works about 70% of the time, the rest are overridden in
101
- # structure_additions.yml
102
- def convert_swift_convention(bban, bank, branch)
103
- bban_regex = iban_registry_to_regex(bban)
104
- bank_regex = iban_registry_to_regex(bank)
105
- branch_regex = branch.nil? ? nil : iban_registry_to_regex(branch)
106
-
107
- non_account_number_regex = [bank_regex, branch_regex].join
108
- account_number_start = (bban_regex.index(non_account_number_regex) || 0) +
109
- non_account_number_regex.length
110
- account_number_regex = bban_regex[account_number_start..-1]
111
-
112
- {
113
- bban_format: bban_regex,
114
- bank_code_format: bank_regex,
115
- branch_code_format: branch_regex,
116
- account_number_format: account_number_regex,
117
- }.compact
83
+ def parse
84
+ lines.each do |line|
85
+ country_code = clean_string(line[COUNTRY_CODE])
86
+
87
+ bban_details = convert_swift_convention(
88
+ country_code: country_code,
89
+ bban_structure: clean_string(line[BBAN_STRUCTURE]),
90
+ bank_code_structure: clean_string(line[BANK_IDENTIFIER_PATTERN]),
91
+ branch_code_structure: clean_string(line[BRANCH_IDENTIFIER_PATTERN]),
92
+ bank_identifier_position: clean_string(line[BANK_IDENTIFIER_POSITION]),
93
+ branch_identifier_position: clean_string(line[BRANCH_IDENTIFIER_POSITION]),
94
+ ) || {}
95
+
96
+ registry[country_code] = {
97
+ iban_example: clean_string(line[IBAN_EXAMPLE]),
98
+ bban_example: clean_string(line[BBAN_EXAMPLE]),
99
+ domestic_account_number_example: clean_string(line[DOMESTIC_ACCOUNT_NUMBER_EXAMPLE]),
100
+ **bban_details,
101
+ }.compact
102
+ end
103
+ end
104
+
105
+ private
106
+
107
+ def clean_string(string)
108
+ return nil if string.nil?
109
+
110
+ string.strip!
111
+ return nil if string == "N/A"
112
+
113
+ string
114
+ end
115
+
116
+ # IBAN Registry has BBAN format (which seems to be accurate), and Bank
117
+ # identifier length, which contains something roughly like the format for the
118
+ # bank code and usually the branch code where applicable. This is a best attempt
119
+ # to convert those from weird SWIFT-talk into regexes, and then work out the
120
+ # account number format regex by taking the bank and branch code regexes off
121
+ # the front of the BBAN format.
122
+ #
123
+ # This works about 90% of the time, the rest are overridden in
124
+ # structure_additions.yml
125
+ def convert_swift_convention( # rubocop:todo Metrics/AbcSize
126
+ country_code:,
127
+ bban_structure:,
128
+ branch_code_structure:,
129
+ bank_code_structure: nil,
130
+ bank_identifier_position: nil,
131
+ branch_identifier_position: nil
132
+ )
133
+ bban_regex = iban_registry_to_regex(bban_structure)
134
+ bank_regex = iban_registry_to_regex(bank_code_structure)
135
+ branch_regex = branch_code_structure.nil? ? nil : iban_registry_to_regex(branch_code_structure)
136
+
137
+ bban_ranges = create_bban_ranges(bban_structure)
138
+ ranges_to_remove = [
139
+ convert_string_range(bank_identifier_position),
140
+ convert_string_range(branch_identifier_position),
141
+ ].compact.uniq
142
+ max_bank_details_index = ranges_to_remove.map(&:last).max
143
+
144
+ _, non_bank_identifier_ranges = bban_ranges.partition do |_, range|
145
+ max_bank_details_index >= range.last
146
+ end
147
+
148
+ account_number_regex = iban_registry_to_regex(non_bank_identifier_ranges.map(&:first).join)
149
+
150
+ {
151
+ bban_format: bban_regex.source,
152
+ bank_code_format: bank_regex.source,
153
+ branch_code_format: branch_regex&.source,
154
+ account_number_format: account_number_regex.source,
155
+ }
156
+ rescue StandardError => e
157
+ puts "-----------------"
158
+ puts "Issue with: #{country_code}"
159
+ puts "\t #{e.message}"
160
+ puts "\t #{e.backtrace}"
161
+ puts "\t -----------------"
162
+ puts "\t country_code: #{country_code}"
163
+ puts "\t bban_structure: #{bban_structure}"
164
+ puts "\t branch_code_structure: #{branch_code_structure}"
165
+ puts "\t bank_code_structure: #{bank_code_structure}"
166
+ puts "\t bank_identifier_position: #{bank_identifier_position}"
167
+ puts "\t branch_identifier_position: #{branch_identifier_position}"
168
+ end
169
+
170
+ # Given "4!n4!n12!c" this returns an array that contains the ranges that cover the
171
+ # structure. Eg; [["4!n", 0..3]]
172
+ def create_bban_ranges(bban_structure)
173
+ arr = bban_structure.scan(/((\d+)![anc])/)
174
+
175
+ start = 0
176
+
177
+ arr.each_with_object([]) do |(structure, length), acc|
178
+ end_number = start + length.to_i - 1
179
+ acc.push([structure, start..end_number])
180
+ start = end_number + 1
181
+ end
182
+ end
183
+
184
+ def convert_string_range(str)
185
+ start_val, end_val = str.split("-").map(&:to_i)
186
+ (start_val - 1)..(end_val - 1)
187
+ rescue StandardError
188
+ nil
189
+ end
190
+
191
+ def iban_registry_to_regex(swift_string)
192
+ regex = swift_string.
193
+ gsub(/(\d+)!n/, '\\d{\1}').
194
+ gsub(/(\d+)!a/, '[A-Z]{\1}').
195
+ gsub(/(\d+)!c/, '[A-Z0-9]{\1}')
196
+ Regexp.new(regex)
197
+ end
118
198
  end
119
199
 
120
- def iban_registry_to_regex(swift_string)
121
- swift_string.gsub(/(\d+)!([nac])/, '\2{\1}').
122
- gsub("n", '\d').
123
- gsub("a", "[A-Z]").
124
- gsub("c", "[A-Z0-9]")
200
+ class IbanStructureFile
201
+ attr_accessor :report, :iban_registry_file
202
+
203
+ def self.call(iban_registry_file, path: "../data/raw/IBANSTRUCTURE.xml")
204
+ iban_structures_file = File.read(File.expand_path(path, __dir__))
205
+ new(iban_registry_file:, iban_structures_file:).parse
206
+ end
207
+
208
+ def initialize(iban_registry_file:, iban_structures_file:)
209
+ @iban_registry_file = iban_registry_file
210
+ @report = Report.parse(iban_structures_file)
211
+ end
212
+
213
+ def parse # rubocop:todo Metrics/AbcSize
214
+ report.countries.each_with_object({}) do |country, hash|
215
+ country_bban = iban_registry_file.registry[country.country_code] || {}
216
+
217
+ hash[country.country_code] = {
218
+ bank_code_position: country.bank_code_position.to_i,
219
+ bank_code_length: country.bank_code_length.to_i,
220
+ branch_code_position: country.branch_code_position.to_i,
221
+ branch_code_length: country.branch_code_length.to_i,
222
+ account_number_position: country.account_number_position.to_i,
223
+ account_number_length: country.account_number_length.to_i,
224
+ total_length: country.total_length.to_i,
225
+ national_id_length: country.national_id_length.to_i,
226
+ **country_bban,
227
+ }
228
+ end
229
+ end
125
230
  end
126
231
 
127
232
  def merge_structures(structures, additions)
128
233
  additions.each_pair do |key, value|
129
- structures[key].merge!(value) if structures.include?(key)
234
+ structures[key].merge!(value).compact! if structures.include?(key)
130
235
  end
131
236
 
132
237
  structures
133
238
  end
134
239
 
240
+ def load_yaml_file(path)
241
+ YAML.safe_load(
242
+ File.read(File.expand_path(path, __dir__)),
243
+ permitted_classes: [Range, Symbol, Regexp],
244
+ )
245
+ end
246
+
135
247
  # Only parse the files if this file is run as an executable (not required in,
136
248
  # as it is in the specs)
137
249
  if __FILE__ == $PROGRAM_NAME
138
- iban_registry_file = CSV.read(
139
- File.expand_path("../data/raw/IBAN_Registry.txt", __dir__),
140
- col_sep: "\t",
141
- headers: true,
142
- encoding: Encoding::ISO_8859_1,
143
- ).to_a.transpose
144
-
145
- iban_registry_file.shift
146
-
147
- iban_structures_file = File.read(
148
- File.expand_path("../data/raw/IBANSTRUCTURE.xml", __dir__),
149
- )
250
+ old_file = load_yaml_file("../data/structures.yml")
150
251
 
151
- iban_structures = get_iban_structures(
152
- iban_structures_file,
153
- iban_registry_file,
154
- )
252
+ iban_registry_file = IbanRegistryTextFile.call
253
+ iban_structures = IbanStructureFile.call(iban_registry_file)
155
254
 
156
- structure_additions = YAML.safe_load(
157
- File.read(File.expand_path("../data/raw/structure_additions.yml", __dir__)),
158
- permitted_classes: [Range, Symbol],
159
- )
255
+ structure_additions = load_yaml_file("../data/raw/structure_additions.yml")
160
256
 
161
257
  complete_structures = merge_structures(iban_structures, structure_additions)
258
+ pseudo_ibans = load_yaml_file("../data/raw/pseudo_ibans.yml")
259
+
260
+ complete_structures.merge!(pseudo_ibans)
162
261
 
163
262
  output_file_path = File.expand_path(
164
263
  "../data/structures.yml",
@@ -166,4 +265,12 @@ if __FILE__ == $PROGRAM_NAME
166
265
  )
167
266
 
168
267
  File.open(output_file_path, "w") { |f| f.write(complete_structures.to_yaml) }
268
+
269
+ new_countries = old_file.keys.to_set ^ complete_structures.keys.to_set
270
+ puts "New countries:"
271
+ new_countries.each do |country|
272
+ puts "#{country} #{complete_structures[country][:iban_example]} #{complete_structures[country][:domestic_account_number_example]}"
273
+ end
169
274
  end
275
+
276
+ # rubocop:enable Layout/LineLength
@@ -8,6 +8,9 @@
8
8
  '10010123':
9
9
  :check_digit_rule: '09'
10
10
  :iban_rule: '000000'
11
+ '10010200':
12
+ :check_digit_rule: '09'
13
+ :iban_rule: '000000'
11
14
  '10010300':
12
15
  :check_digit_rule: '09'
13
16
  :iban_rule: '000000'
@@ -1709,9 +1712,6 @@
1709
1712
  '25850110':
1710
1713
  :check_digit_rule: '00'
1711
1714
  :iban_rule: '000000'
1712
- '25851335':
1713
- :check_digit_rule: '00'
1714
- :iban_rule: '000000'
1715
1715
  '25851660':
1716
1716
  :check_digit_rule: '00'
1717
1717
  :iban_rule: '000000'
@@ -3155,6 +3155,9 @@
3155
3155
  '37021548':
3156
3156
  :check_digit_rule: '09'
3157
3157
  :iban_rule: '000000'
3158
+ '37027000':
3159
+ :check_digit_rule: '09'
3160
+ :iban_rule: '000000'
3158
3161
  '37030700':
3159
3162
  :check_digit_rule: '19'
3160
3163
  :iban_rule: '000000'
@@ -4622,9 +4625,6 @@
4622
4625
  '50030010':
4623
4626
  :check_digit_rule: '09'
4624
4627
  :iban_rule: '000000'
4625
- '50030100':
4626
- :check_digit_rule: '00'
4627
- :iban_rule: '000000'
4628
4628
  '50030500':
4629
4629
  :check_digit_rule: '09'
4630
4630
  :iban_rule: '000000'
@@ -4856,6 +4856,54 @@
4856
4856
  '50070024':
4857
4857
  :check_digit_rule: '63'
4858
4858
  :iban_rule: '002002'
4859
+ '50070050':
4860
+ :check_digit_rule: '09'
4861
+ :iban_rule: '000000'
4862
+ '50070051':
4863
+ :check_digit_rule: '09'
4864
+ :iban_rule: '000000'
4865
+ '50070052':
4866
+ :check_digit_rule: '09'
4867
+ :iban_rule: '000000'
4868
+ '50070053':
4869
+ :check_digit_rule: '09'
4870
+ :iban_rule: '000000'
4871
+ '50070054':
4872
+ :check_digit_rule: '09'
4873
+ :iban_rule: '000000'
4874
+ '50070055':
4875
+ :check_digit_rule: '09'
4876
+ :iban_rule: '000000'
4877
+ '50070056':
4878
+ :check_digit_rule: '09'
4879
+ :iban_rule: '000000'
4880
+ '50070057':
4881
+ :check_digit_rule: '09'
4882
+ :iban_rule: '000000'
4883
+ '50070058':
4884
+ :check_digit_rule: '09'
4885
+ :iban_rule: '000000'
4886
+ '50070059':
4887
+ :check_digit_rule: '09'
4888
+ :iban_rule: '000000'
4889
+ '50070060':
4890
+ :check_digit_rule: '09'
4891
+ :iban_rule: '000000'
4892
+ '50070061':
4893
+ :check_digit_rule: '09'
4894
+ :iban_rule: '000000'
4895
+ '50070062':
4896
+ :check_digit_rule: '09'
4897
+ :iban_rule: '000000'
4898
+ '50070063':
4899
+ :check_digit_rule: '09'
4900
+ :iban_rule: '000000'
4901
+ '50070064':
4902
+ :check_digit_rule: '09'
4903
+ :iban_rule: '000000'
4904
+ '50070065':
4905
+ :check_digit_rule: '09'
4906
+ :iban_rule: '000000'
4859
4907
  '50070324':
4860
4908
  :check_digit_rule: '63'
4861
4909
  :iban_rule: '002002'
@@ -4982,9 +5030,6 @@
4982
5030
  '50110200':
4983
5031
  :check_digit_rule: '09'
4984
5032
  :iban_rule: '000000'
4985
- '50110300':
4986
- :check_digit_rule: '10'
4987
- :iban_rule: '000000'
4988
5033
  '50110400':
4989
5034
  :check_digit_rule: '09'
4990
5035
  :iban_rule: '000000'
@@ -5473,7 +5518,7 @@
5473
5518
  :iban_rule: '002900'
5474
5519
  '51210801':
5475
5520
  :check_digit_rule: '09'
5476
- :iban_rule: '000000'
5521
+ :iban_rule: '002900'
5477
5522
  '51210802':
5478
5523
  :check_digit_rule: '09'
5479
5524
  :iban_rule: '002900'
@@ -8507,12 +8552,6 @@
8507
8552
  '70120700':
8508
8553
  :check_digit_rule: '00'
8509
8554
  :iban_rule: '000000'
8510
- '70130700':
8511
- :check_digit_rule: '09'
8512
- :iban_rule: '000000'
8513
- '70130799':
8514
- :check_digit_rule: '09'
8515
- :iban_rule: '000000'
8516
8555
  '70130800':
8517
8556
  :check_digit_rule: '88'
8518
8557
  :iban_rule: '000000'
@@ -8693,9 +8732,6 @@
8693
8732
  '70220300':
8694
8733
  :check_digit_rule: '09'
8695
8734
  :iban_rule: '000000'
8696
- '70220800':
8697
- :check_digit_rule: '07'
8698
- :iban_rule: '000000'
8699
8735
  '70220900':
8700
8736
  :check_digit_rule: '61'
8701
8737
  :iban_rule: '000000'
@@ -9483,7 +9519,7 @@
9483
9519
  :check_digit_rule: '88'
9484
9520
  :iban_rule: '000000'
9485
9521
  '75090500':
9486
- :check_digit_rule: '84'
9522
+ :check_digit_rule: '09'
9487
9523
  :iban_rule: '000000'
9488
9524
  '75090900':
9489
9525
  :check_digit_rule: '91'
@@ -10178,6 +10214,9 @@
10178
10214
  '81000000':
10179
10215
  :check_digit_rule: '09'
10180
10216
  :iban_rule: '004201'
10217
+ '81010400':
10218
+ :check_digit_rule: '27'
10219
+ :iban_rule: '000000'
10181
10220
  '81020500':
10182
10221
  :check_digit_rule: '09'
10183
10222
  :iban_rule: '000000'