ibandit 0.2.1 → 0.3.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.
@@ -0,0 +1,298 @@
1
+ module Ibandit
2
+ module LocalDetailsCleaner
3
+ SUPPORTED_COUNTRY_CODES = %w(AT BE CY DE EE ES FI FR GB IE IT LT LU LV MC NL
4
+ PT SI SK SM).freeze
5
+
6
+ def self.clean(local_details)
7
+ country_code = local_details[:country_code]
8
+
9
+ return local_details unless can_clean?(country_code, local_details)
10
+
11
+ local_details.merge(
12
+ public_send(:"clean_#{country_code.downcase}_details", local_details))
13
+ end
14
+
15
+ ###########
16
+ # Helpers #
17
+ ###########
18
+
19
+ def self.can_clean?(country_code, local_details)
20
+ SUPPORTED_COUNTRY_CODES.include?(country_code) &&
21
+ fields_for?(country_code, local_details)
22
+ end
23
+
24
+ def self.fields_for?(country_code, opts)
25
+ required_fields(country_code).all? { |argument| opts[argument] }
26
+ end
27
+
28
+ def self.required_fields(country_code)
29
+ case country_code
30
+ when 'AT', 'CY', 'DE', 'FI', 'LT', 'LU', 'LV', 'NL', 'SI', 'SK'
31
+ %i(bank_code account_number)
32
+ when 'BE', 'EE', 'ES'
33
+ %i(account_number)
34
+ when 'GB', 'IE'
35
+ if Ibandit.bic_finder.nil? then %i(bank_code branch_code account_number)
36
+ else %i(branch_code account_number)
37
+ end
38
+ else
39
+ %i(bank_code branch_code account_number)
40
+ end
41
+ end
42
+
43
+ ##########################
44
+ # Country-specific logic #
45
+ ##########################
46
+
47
+ def self.clean_at_details(local_details)
48
+ # Account number may be 4-11 digits long.
49
+ # Add leading zeros to account number if < 11 digits.
50
+ return {} unless local_details[:account_number].length >= 4
51
+ {
52
+ bank_code: local_details[:bank_code],
53
+ account_number: local_details[:account_number].rjust(11, '0')
54
+ }
55
+ end
56
+
57
+ def self.clean_be_details(local_details)
58
+ account_number = local_details[:account_number].tr('-', '')
59
+
60
+ {
61
+ bank_code: local_details[:bank_code] || account_number.slice(0, 3),
62
+ account_number: account_number
63
+ }
64
+ end
65
+
66
+ def self.clean_cy_details(local_details)
67
+ # Account number may be 7-16 digits long.
68
+ # Add leading zeros to account number if < 16 digits.
69
+ cleaned_bank_code = local_details[:bank_code].gsub(/[-\s]/, '')
70
+
71
+ bank_code = cleaned_bank_code.slice(0, 3)
72
+ branch_code =
73
+ if local_details[:branch_code]
74
+ local_details[:branch_code]
75
+ elsif cleaned_bank_code.length > 3
76
+ cleaned_bank_code[3..-1]
77
+ end
78
+ account_number =
79
+ if local_details[:account_number].length >= 7
80
+ local_details[:account_number].rjust(16, '0')
81
+ else
82
+ local_details[:account_number]
83
+ end
84
+
85
+ {
86
+ bank_code: bank_code,
87
+ branch_code: branch_code,
88
+ account_number: account_number
89
+ }
90
+ end
91
+
92
+ def self.clean_de_details(local_details)
93
+ # Account number may be up to 10 digits long.
94
+ # Add leading zeros to account number if < 10 digits.
95
+ #
96
+ # There are many exceptions to the way German bank details translate
97
+ # into an IBAN, detailed into a 200 page document compiled by the
98
+ # Bundesbank, and handled by the GermanDetailsConverter class.
99
+ converted_details = GermanDetailsConverter.convert(local_details)
100
+
101
+ return {} unless converted_details[:account_number].length >= 4
102
+
103
+ {
104
+ bank_code: converted_details[:bank_code],
105
+ account_number: converted_details[:account_number].rjust(10, '0')
106
+ }
107
+ end
108
+
109
+ def self.clean_ee_details(local_details)
110
+ # Account number may be up to 14 characters long.
111
+ # Add leading zeros to account number if < 14 digits.
112
+ #
113
+ # Bank code can be found by extracted from the first two digits of the
114
+ # account number and converted using the rules at
115
+ # http://www.pangaliit.ee/en/settlements-and-standards/bank-codes-of-estonian-banks
116
+ domestic_bank_code =
117
+ local_details[:account_number].gsub(/\A0+/, '').slice(0, 2)
118
+
119
+ iban_bank_code =
120
+ case domestic_bank_code
121
+ when '11' then '22'
122
+ when '93' then '00'
123
+ else domestic_bank_code
124
+ end
125
+
126
+ account_number = local_details[:account_number].rjust(14, '0')
127
+
128
+ { bank_code: iban_bank_code, account_number: account_number }
129
+ end
130
+
131
+ def self.clean_es_details(local_details)
132
+ # This method supports being passed the component IBAN parts, as defined
133
+ # by SWIFT, or a single 20 digit string.
134
+ if local_details[:bank_code] && local_details[:branch_code]
135
+ bank_code = local_details[:bank_code]
136
+ branch_code = local_details[:branch_code]
137
+ account_number = local_details[:account_number]
138
+ else
139
+ cleaned_account_number = local_details[:account_number].tr('-', '')
140
+
141
+ bank_code = cleaned_account_number.slice(0, 4)
142
+ branch_code = cleaned_account_number.slice(4, 4)
143
+ account_number = cleaned_account_number[8..-1]
144
+ end
145
+
146
+ {
147
+ bank_code: bank_code,
148
+ branch_code: branch_code,
149
+ account_number: account_number
150
+ }
151
+ end
152
+
153
+ def self.clean_fi_details(local_details)
154
+ # Finnish account numbers need to be expanded into "electronic format"
155
+ # by adding zero-padding. The expansion method depends on the first
156
+ # character of the bank code.
157
+ account_number =
158
+ if %w(4 5 6).include?(local_details[:bank_code][0])
159
+ [
160
+ local_details[:account_number][0],
161
+ local_details[:account_number][1..-1].rjust(7, '0')
162
+ ].join
163
+ else
164
+ local_details[:account_number].rjust(8, '0')
165
+ end
166
+
167
+ {
168
+ bank_code: local_details[:bank_code],
169
+ account_number: account_number
170
+ }
171
+ end
172
+
173
+ def self.clean_fr_details(local_details)
174
+ {
175
+ bank_code: local_details[:bank_code],
176
+ branch_code: local_details[:branch_code],
177
+ account_number: local_details[:account_number].gsub(/[-\s]/, '')
178
+ }
179
+ end
180
+
181
+ def self.clean_gb_details(local_details)
182
+ # Account number may be 6-8 digits
183
+ # Add leading zeros to account number if < 8 digits.
184
+ branch_code = local_details[:branch_code].gsub(/[-\s]/, '')
185
+
186
+ if local_details[:bank_code]
187
+ bank_code = local_details[:bank_code]
188
+ else
189
+ bic = Ibandit.find_bic('GB', branch_code)
190
+ bank_code = bic.nil? ? nil : bic.slice(0, 4)
191
+ end
192
+
193
+ account_number = local_details[:account_number].gsub(/[-\s]/, '')
194
+ account_number = account_number.rjust(8, '0') if account_number.length > 5
195
+
196
+ {
197
+ bank_code: bank_code,
198
+ branch_code: branch_code,
199
+ account_number: account_number
200
+ }
201
+ end
202
+
203
+ def self.clean_lt_details(local_details)
204
+ # Lithuanian national bank details were replaced with IBANs in 2004.
205
+ local_details
206
+ end
207
+
208
+ def self.clean_lu_details(local_details)
209
+ # Luxembourgian national bank details were replaced with IBANs in 2002.
210
+ local_details
211
+ end
212
+
213
+ def self.clean_lv_details(local_details)
214
+ # Latvian national bank details were replaced with IBANs in 2004.
215
+ local_details
216
+ end
217
+
218
+ def self.clean_ie_details(local_details)
219
+ # Ireland uses the same local details as the United Kingdom
220
+ branch_code = local_details[:branch_code].gsub(/[-\s]/, '')
221
+
222
+ if local_details[:bank_code]
223
+ bank_code = local_details[:bank_code]
224
+ else
225
+ bic = Ibandit.find_bic('IE', branch_code)
226
+ bank_code = bic.nil? ? nil : bic.slice(0, 4)
227
+ end
228
+
229
+ account_number = local_details[:account_number].gsub(/[-\s]/, '')
230
+ account_number = account_number.rjust(8, '0') if account_number.length > 5
231
+
232
+ {
233
+ bank_code: bank_code,
234
+ branch_code: branch_code,
235
+ account_number: account_number
236
+ }
237
+ end
238
+
239
+ def self.clean_it_details(local_details)
240
+ # Add leading zeros to account number if < 12 digits.
241
+ {
242
+ bank_code: local_details[:bank_code],
243
+ branch_code: local_details[:branch_code],
244
+ account_number: local_details[:account_number].rjust(12, '0')
245
+ }
246
+ end
247
+
248
+ def self.clean_mc_details(local_details)
249
+ # Monaco uses the same local details method as France
250
+ clean_fr_details(local_details)
251
+ end
252
+
253
+ def self.clean_nl_details(local_details)
254
+ # Add leading zeros to account number if < 10 digits.
255
+ {
256
+ bank_code: local_details[:bank_code],
257
+ account_number: local_details[:account_number].rjust(10, '0')
258
+ }
259
+ end
260
+
261
+ def self.clean_pt_details(local_details)
262
+ local_details
263
+ end
264
+
265
+ def self.clean_si_details(local_details)
266
+ # Add leading zeros to account number if < 10 digits.
267
+ {
268
+ bank_code: local_details[:bank_code],
269
+ account_number: local_details[:account_number].rjust(10, '0')
270
+ }
271
+ end
272
+
273
+ def self.clean_sk_details(local_details)
274
+ # The SWIFT definition of a Slovakian IBAN includes both the account
275
+ # number prefix and the account number. This method therefore supports
276
+ # passing those fields concatenated.
277
+ account_number =
278
+ if local_details.include?(:account_number_prefix)
279
+ [
280
+ local_details[:account_number_prefix].rjust(6, '0'),
281
+ local_details[:account_number].rjust(10, '0')
282
+ ].join
283
+ else
284
+ local_details[:account_number].tr('-', '').rjust(16, '0')
285
+ end
286
+
287
+ {
288
+ bank_code: local_details[:bank_code],
289
+ account_number: account_number
290
+ }
291
+ end
292
+
293
+ def self.clean_sm_details(local_details)
294
+ # San Marino uses the same local details method as France
295
+ clean_it_details(local_details)
296
+ end
297
+ end
298
+ end
@@ -1,3 +1,3 @@
1
1
  module Ibandit
2
- VERSION = '0.2.1'.freeze
2
+ VERSION = '0.3.0'.freeze
3
3
  end
data/lib/ibandit.rb CHANGED
@@ -2,7 +2,9 @@ require 'ibandit/version'
2
2
  require 'ibandit/errors'
3
3
  require 'ibandit/iban'
4
4
  require 'ibandit/german_details_converter'
5
- require 'ibandit/iban_builder'
5
+ require 'ibandit/iban_splitter'
6
+ require 'ibandit/iban_assembler'
7
+ require 'ibandit/local_details_cleaner'
6
8
  require 'ibandit/check_digit'
7
9
 
8
10
  module Ibandit
@@ -13,5 +15,11 @@ module Ibandit
13
15
  raise NotImplementedError, 'BIC finder is not defined' unless @bic_finder
14
16
  @bic_finder.call(country_code, national_id)
15
17
  end
18
+
19
+ def structures
20
+ @structures ||= YAML.load_file(
21
+ File.expand_path('../../data/structures.yml', __FILE__)
22
+ )
23
+ end
16
24
  end
17
25
  end