iban_calculator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 19c90f0379c87c7251c554191b6ee1ca82f7e7c5
4
+ data.tar.gz: 1906317a98ebfa25ec45d4bdff1a0c3d01448ab0
5
+ SHA512:
6
+ metadata.gz: 2210281de1e0c117cf9881d0f0adea74b8f37271a48032dc5a735a9068fdc3e49e69a990ec8bf650f893eb25c865373582a4c5d5746050f4d99f261ee4b0372a
7
+ data.tar.gz: 4d69c1cef82b442417c2a2096a408eb394f5d1ad8673cdef9c047a245625b8a2e2271e8a2d36200ea583460a15809d0cc8e6db7ef753c4f09b7692f9b2028035
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in iban_calculator.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Maximilian Schulz
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # IbanCalculator
2
+
3
+ A wrapper for ibanrechner.de API. It allows converting bank account data from legacy syntax to new SEPA IBAN/BIC.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'iban_calculator'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install iban_calculator
18
+
19
+ ## Usage
20
+
21
+ In order to use iban calculator, you need to create an account at [iban-bic.com](http://www.iban-bic.com/).
22
+
23
+ In case you are using rails, configure your app like this:
24
+
25
+ # config/initializers/iban_calculator.rb
26
+ IbanCalculator.user = 'your_username',
27
+ IbanCalculator.password = 'your_password'
28
+ IbanCalculator.logger = Rails.logger
29
+
30
+ Whenever you need to convert European legacy account data to new SEPA IBAN format:
31
+
32
+ # app/models/your_model.rb
33
+ IbanCalculator.calculate_iban country: 'DE', account_number: '123', bank_code: '456'
34
+
35
+ Example data can be found at: http://www.iban-bic.com/sample_accounts.html
36
+
37
+
38
+ ## Contributing
39
+
40
+ 1. Fork it ( https://github.com/[my-github-username]/iban_calculator/fork )
41
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
42
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
43
+ 4. Push to the branch (`git push origin my-new-feature`)
44
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'iban_calculator/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "iban_calculator"
8
+ spec.version = IbanCalculator::VERSION
9
+ spec.authors = ["Maximilian Schulz"]
10
+ spec.email = ["m.schulz@kulturfluss.de"]
11
+ spec.summary = %q{Calculate IBAN and BIC for countries of Single European Payments Area (SEPA).}
12
+ spec.description = %q{At the moment the gem is just a wrapper for the ibanrechner.de API.}
13
+ spec.homepage = "https://github.com/railslove/iban_calculator"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activesupport", "~> 4"
22
+ spec.add_dependency "savon", "~> 2"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.6"
25
+ spec.add_development_dependency "rake", "~> 0"
26
+ spec.add_development_dependency "rspec", "~> 3"
27
+ end
@@ -0,0 +1,104 @@
1
+ require 'savon'
2
+
3
+ # Return codes and their meaning:
4
+ #
5
+ # 0 = all checks were successful
6
+ #
7
+ # 1 = sub account number has been added automatically
8
+ # 2 = account number did not include a checksum
9
+ # 4 = checksum has not been checked
10
+ # 8 = bank code has not been checked
11
+ #
12
+ # 32 = A sub account number might be required, but could not be determined autoamtically
13
+ #
14
+ # 128 = checksum for account_number is invalid
15
+ # 256 = bank_code could not be found is database
16
+ # 512 = account_number has an invalid length
17
+ # 1024 = bank_code has an invalid length
18
+ # 4096 = data is missing (i.e. country code)
19
+ # 8192= country is not yet supported
20
+ #
21
+ module IbanCalculator
22
+ class IbanBic
23
+ ITALIAN_IBAN_LENGTH = 27
24
+ PREFIX_AND_CHECKSUM_LENGTH = 4
25
+
26
+ VALID_RESPONSE_CODE = 0..31
27
+ PROBABLY_VALID_RESPONSE_CODE = 32..127
28
+ SERVICE_ERROR_RESPONSE_CODE = 65536
29
+
30
+ attr_accessor :user, :password, :url, :logger
31
+
32
+ def initialize(user, password, url, logger)
33
+ self.user = user
34
+ self.password = password
35
+ self.url = url
36
+ self.logger = logger
37
+ end
38
+
39
+ # You should provide country, bank_code, and account_number. (cin, abi, and cab for Italian accounts)
40
+ def calculate_iban(attributes)
41
+ payload = iban_payload(attributes)
42
+ response = client.call(:calculate_iban, message: payload).body[:calculate_iban_response][:return]
43
+ log "iban lookup attributes=#{attributes} payload=#{payload} response=#{response}"
44
+
45
+ case return_code = response[:return_code].to_i
46
+ when VALID_RESPONSE_CODE
47
+ formatted_result(response)
48
+ when PROBABLY_VALID_RESPONSE_CODE
49
+ log "iban check needs manual check return_code=#{return_code}"
50
+ formatted_result(response)
51
+ when SERVICE_ERROR_RESPONSE_CODE
52
+ log "iban check failed return_code=#{return_code}"
53
+ fail ServiceError, 'Service could not handle the request'
54
+ else
55
+ log "iban check invalid return_code=#{return_code}"
56
+ fail InvalidData.new('Invalid input data', return_code)
57
+ end
58
+ end
59
+
60
+ def italian_account_number(attributes = {})
61
+ return {} unless attributes['country'].to_s.upcase == 'IT'
62
+ left_length = ITALIAN_IBAN_LENGTH - PREFIX_AND_CHECKSUM_LENGTH - attributes['account'].length
63
+ left_side = [attributes['cin'], attributes['abi'], attributes['cab']].join.ljust(left_length, '0')
64
+ { 'account' => left_side + attributes['account'] }
65
+ end
66
+
67
+ def default_payload
68
+ { country: '', bank_code: '', account: '', user: user, password: password, bic: '', legacy_mode: 0 }
69
+ end
70
+
71
+ def formatted_result(data)
72
+ { iban: data[:iban],
73
+ bics: process_bic_candidates(data[:bic_candidates]),
74
+ country: data[:country],
75
+ bank_code: data[:bank_code],
76
+ bank: data[:bank],
77
+ account_number: data[:account_number],
78
+ updated_at: Date.parse(data[:data_age]) }
79
+ end
80
+
81
+ def process_bic_candidates(candidates)
82
+ [candidates[:item].select { |key, value| [:bic, :zip, :city].include?(key) && value.kind_of?(String) }]
83
+ rescue
84
+ log "Could not handle candidates=#{candidates}"
85
+ fail ArgumentError, "Could not handle BIC response"
86
+ end
87
+
88
+ def iban_payload(attributes)
89
+ attributes = attributes.with_indifferent_access
90
+ attributes['account'] = attributes.delete('account_number')
91
+ normalized_attributes = attributes.merge(italian_account_number(attributes))
92
+ payload = normalized_attributes.select { |k,_| %w(country account bank_code).include?(k) }
93
+ default_payload.merge(payload.symbolize_keys)
94
+ end
95
+
96
+ def log(message)
97
+ logger.info message
98
+ end
99
+
100
+ def client
101
+ @client ||= Savon.client(wsdl: url)
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,35 @@
1
+ module IbanCalculator
2
+ class InvalidData < StandardError
3
+ CODES = {
4
+ 128 => [:account_number, [:checksum_failed]],
5
+ 256 => [:bank_code, [:not_found]],
6
+ 512 => [:account_number, [:invalid_length]],
7
+ 1024 => [:bank_code, [:invalid_length]],
8
+ 4096 => [:base, [:data_missing]],
9
+ 8192 => [:country, [:not_supported]],
10
+ }
11
+
12
+ attr_accessor :errors
13
+
14
+ def initialize(msg, error_code)
15
+ self.errors = resolve_error_code(error_code)
16
+ super(msg)
17
+ end
18
+
19
+ def resolve_error_code(error_code)
20
+ known_error_codes(error_code).reduce(Hash.new([])) do |hsh, item|
21
+ error = CODES[item]
22
+ hsh[error[0]] += error[1]
23
+ hsh
24
+ end
25
+ end
26
+
27
+ def known_error_codes(error_code)
28
+ error_codes(error_code) & CODES.keys
29
+ end
30
+
31
+ def error_codes(n)
32
+ (0..13).map { |i| n & 2**i } - [0]
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ module IbanCalculator
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,22 @@
1
+ require 'iban_calculator/version'
2
+ require 'active_support/configurable'
3
+ require 'active_support/core_ext/hash'
4
+ require 'logger'
5
+ require 'iban_calculator/iban_bic'
6
+ require 'iban_calculator/invalid_data'
7
+
8
+ module IbanCalculator
9
+ include ActiveSupport::Configurable
10
+
11
+ config_accessor(:url) { 'https://ssl.ibanrechner.de/soap/?wsdl' }
12
+ config_accessor(:user) { '' }
13
+ config_accessor(:password) { '' }
14
+ config_accessor(:logger) { Logger.new(STDOUT) }
15
+
16
+ ServiceError = Class.new(StandardError)
17
+
18
+ def self.calculate_iban(attributes = {})
19
+ client = IbanBic.new(config.user, config.password, config.url, config.logger)
20
+ client.calculate_iban(attributes)
21
+ end
22
+ end
@@ -0,0 +1,244 @@
1
+ describe IbanCalculator::IbanBic do
2
+ subject { described_class.new('user', 'pass', 'url', Logger.new(STDOUT) ) }
3
+
4
+ before { allow(subject.logger).to receive(:info) }
5
+
6
+ describe '#italian_account_number' do
7
+ it 'returns an empty hash if not all fields are provided' do
8
+ expect(subject.italian_account_number).to eq({})
9
+ end
10
+
11
+ it 'returns hash with correct account number if valid data is provided' do
12
+ expect(subject.italian_account_number(
13
+ 'country' => 'IT',
14
+ 'cab' => '03280',
15
+ 'abi' => '03002',
16
+ 'cin' => 'D',
17
+ 'account' => '400162854',
18
+ )).to eq('account' => 'D0300203280000400162854')
19
+ end
20
+ end
21
+
22
+ describe '#default_payload' do
23
+ it 'includes account data' do
24
+ expect(subject.default_payload).to match hash_including(user: 'user', password: 'pass')
25
+ end
26
+ end
27
+
28
+ describe '#process_bic_candidates' do
29
+ context 'known single BIC payload' do
30
+ let(:payload) { valid_payload[:bic_candidates] }
31
+
32
+ it 'returns an array' do
33
+ expect(subject.process_bic_candidates(payload)).to be_kind_of(Array)
34
+ end
35
+
36
+ it 'returns its bank\'s bic' do
37
+ expect(subject.process_bic_candidates(payload).first).to match hash_including(bic: 'BYLADEM1001')
38
+ end
39
+
40
+ it 'returns its bank\'s zip' do
41
+ expect(subject.process_bic_candidates(payload).first).to match hash_including(zip: '10117')
42
+ end
43
+
44
+ it 'returns its bank\'s city' do
45
+ expect(subject.process_bic_candidates(payload).first).to match hash_including(city: 'Berlin')
46
+ end
47
+
48
+ context 'empty fields' do
49
+ let(:payload) { {:item=>{
50
+ :bic=>"UNCRITMM",
51
+ :zip=>{:"@xsi:type"=>"xsd:string"},
52
+ :city=>{:"@xsi:type"=>"xsd:string"},
53
+ :wwwcount=>"0",
54
+ :sampleurl=>{:"@xsi:type"=>"xsd:string"},
55
+ :"@xsi:type"=>"tns:BICStruct"
56
+ },
57
+ :"@xsi:type"=>"SOAP-ENC:Array",
58
+ :"@soap_enc:array_type"=>"tns:BICStruct[1]"} }
59
+
60
+ it 'ignores empty zip' do
61
+ expect(subject.process_bic_candidates(payload).first.keys).to_not include(:zip)
62
+ end
63
+
64
+ it 'ignores empty city' do
65
+ expect(subject.process_bic_candidates(payload).first.keys).to_not include(:city)
66
+ end
67
+ end
68
+ end
69
+
70
+ context 'unknown payload' do
71
+ let(:payload) { { :items => [], :"@xsi:type" => 'SOAP-ENC:Array' } }
72
+
73
+ it 'logs the payload' do
74
+ subject.process_bic_candidates(payload) rescue
75
+ expect(subject.logger).to have_received(:info)
76
+ end
77
+
78
+ it 'raises an exception' do
79
+ expect { subject.process_bic_candidates(payload) }.to raise_exception(ArgumentError)
80
+ end
81
+ end
82
+ end
83
+
84
+ describe '#formatted_result' do
85
+ before { allow(subject).to receive(:process_bic_candidates).and_return(['data']) }
86
+
87
+ it 'returns a valid ruby date for last update date' do
88
+ expect(subject.formatted_result(valid_payload)[:updated_at]).to be_kind_of(Date)
89
+ end
90
+
91
+ it 'transforms the list of bic candidates' do
92
+ subject.formatted_result(valid_payload)
93
+ expect(subject).to have_received(:process_bic_candidates)
94
+ end
95
+
96
+ it 'includes iban' do
97
+ expect(subject.formatted_result(valid_payload).keys).to include(:iban)
98
+ end
99
+ end
100
+
101
+ describe '#iban_payload' do
102
+ context 'italian data is provided' do
103
+ before { allow(subject).to receive(:italian_account_number).and_return({ 'account' => 'italy-123' }) }
104
+
105
+ it 'normalizes italian account data' do
106
+ subject.iban_payload({})
107
+ expect(subject).to have_received(:italian_account_number)
108
+ end
109
+
110
+ it 'merges italian data' do
111
+ expect(subject.iban_payload({ 'country' => 'IT' })).to match(hash_including(account: 'italy-123'))
112
+ end
113
+
114
+ it 'strips italian data' do
115
+ expect(subject.iban_payload({ 'cin' => '123' }).keys).to_not include('cin')
116
+ end
117
+ end
118
+
119
+ it 'adds default payload' do
120
+ expect(subject.iban_payload({}).keys).to include(:user, :password, :legacy_mode)
121
+ end
122
+
123
+ it 'overrides default data' do
124
+ expect(subject.iban_payload({ bank_code: '123' })).to match hash_including(bank_code: '123')
125
+ end
126
+
127
+ it 'replaces account_number with account' do
128
+ expect(subject.iban_payload({ account_number: '123' })).to match hash_including(account: '123')
129
+ end
130
+ end
131
+
132
+ describe '#calculate_iban' do
133
+ before { allow(subject.client).to receive(:call).and_return(response) }
134
+
135
+ context 'valid response' do
136
+ let(:response) { double(body: { calculate_iban_response: { return: valid_payload } }) }
137
+
138
+ it 'returns a formatted response' do
139
+ allow(subject).to receive(:formatted_result)
140
+ subject.calculate_iban({})
141
+ expect(subject).to have_received(:formatted_result)
142
+ end
143
+
144
+ it 'calls the client with the generated payload' do
145
+ subject.calculate_iban({})
146
+ expect(subject.client).to have_received(:call).with(:calculate_iban, message: anything)
147
+ end
148
+ end
149
+
150
+ context 'probably valid response' do
151
+ let(:response) { double(body: { calculate_iban_response: { return: valid_payload.merge(return_code: '32') } }) }
152
+
153
+ it 'logs a message' do
154
+ subject.calculate_iban({}) rescue IbanCalculator::InvalidData
155
+ expect(subject.logger).to have_received(:info).with(/needs manual check/)
156
+ end
157
+
158
+ it 'returns a formatted response' do
159
+ allow(subject).to receive(:formatted_result)
160
+ subject.calculate_iban({})
161
+ expect(subject).to have_received(:formatted_result)
162
+ end
163
+ end
164
+
165
+ context 'invalid response' do
166
+ let(:response) { double(body: { calculate_iban_response: { return: valid_payload.merge(return_code: '128') } }) }
167
+
168
+ it 'logs a message' do
169
+ subject.calculate_iban({}) rescue IbanCalculator::InvalidData
170
+ expect(subject.logger).to have_received(:info).with(/iban check invalid/)
171
+ end
172
+
173
+ it 'fails with invalid data exception' do
174
+ expect{ subject.calculate_iban({}) }.to raise_exception(IbanCalculator::InvalidData)
175
+ end
176
+ end
177
+
178
+ context 'server error response' do
179
+ let(:response) { double(body: { calculate_iban_response: { return: valid_payload.merge(return_code: '65536') } }) }
180
+
181
+ it 'logs a message' do
182
+ subject.calculate_iban({}) rescue IbanCalculator::ServiceError
183
+ expect(subject.logger).to have_received(:info).with(/iban check failed/)
184
+ end
185
+
186
+ it 'fails with service error exception' do
187
+ expect{ subject.calculate_iban({}) }.to raise_exception(IbanCalculator::ServiceError)
188
+ end
189
+ end
190
+ end
191
+
192
+ def valid_payload
193
+ {
194
+ :iban=>"DE59120300001111236988",
195
+ :result=>"passed",
196
+ :return_code=>"0",
197
+ :ibanrueck_return_code=>{
198
+ :"@xsi:type"=>"xsd:string"
199
+ },
200
+ :checks=>{
201
+ :item=>["length", "bank_code", "account_number"],
202
+ :"@xsi:type"=>"SOAP-ENC:Array",
203
+ :"@soap_enc:array_type"=>"xsd:string[3]"
204
+ },
205
+ :bic_candidates=>{
206
+ :item=>{
207
+ :bic=>"BYLADEM1001",
208
+ :zip=>"10117",
209
+ :city=>"Berlin",
210
+ :wwwcount=>"0",
211
+ :sampleurl=>{:"@xsi:type"=>"xsd:string"},
212
+ :"@xsi:type"=>"tns:BICStruct"
213
+ },
214
+ :"@xsi:type"=>"SOAP-ENC:Array",
215
+ :"@soap_enc:array_type"=>"tns:BICStruct[1]"
216
+ },
217
+ :country=>"DE",
218
+ :bank_code=>"12030000",
219
+ :alternative_bank_code=>{:"@xsi:type"=>"xsd:string"},
220
+ :bank=>"Deutsche Kreditbank Berlin",
221
+ :bank_address=>{:"@xsi:type"=>"xsd:string"},
222
+ :bank_url=>{:"@xsi:type"=>"xsd:string"},
223
+ :branch=>{:"@xsi:type"=>"xsd:string"},
224
+ :branch_code=>{:"@xsi:type"=>"xsd:string"},
225
+ :in_scl_directory=>"yes",
226
+ :sct=>"yes",
227
+ :sdd=>"yes",
228
+ :b2b=>"yes",
229
+ :account_number=>"1011856976",
230
+ :alternative_account_number=>{:"@xsi:type"=>"xsd:string"},
231
+ :account_validation_method=>"00",
232
+ :account_validation=>"Methode 00, Konto 1111236988, BLZ 12030000, Prüfziffer 6 steht an Position 10, erwartete Prüfziffer: 6. Überblick über die Berechnung: Nimm die Ziffern auf den Positionen 1 bis 9 - hier: 1111236988 -, multipliziere sie von rechts nach links mit den Gewichten 2,1,2,1,2,1,2,1,2, addiere die Quersummen der Produkte, bilde den Rest der Division durch 10, ziehe das Ergebnis von 10 ab, und das Ergebnis modulo 10 ist die erwartete Prüfziffer.",
233
+ :length_check=>"passed",
234
+ :account_check=>"passed",
235
+ :bank_code_check=>"passed",
236
+ :bic_plausibility_check=>{:"@xsi:type"=>"xsd:string"},
237
+ :data_age=>"20140525",
238
+ :iba_nformat=>"DEkk BBBB BBBB CCCC CCCC CC",
239
+ :formatcomment=>"B = sort code (BLZ), C = account No.",
240
+ :balance=>"4",
241
+ :"@xsi:type"=>"tns:IBANCalcResStruct"
242
+ }
243
+ end
244
+ end
@@ -0,0 +1,51 @@
1
+ describe IbanCalculator do
2
+ describe '.url' do
3
+ it 'defaults to ibanrechner.de' do
4
+ expect(IbanCalculator.url).to eq('https://ssl.ibanrechner.de/soap/?wsdl')
5
+ end
6
+
7
+ it 'allows overriding' do
8
+ IbanCalculator.url = 'http://mytest.com'
9
+ expect(IbanCalculator.url).to eq('http://mytest.com')
10
+ IbanCalculator.url = 'https://ssl.ibanrechner.de/soap/?wsdl'
11
+ end
12
+ end
13
+
14
+ describe '.user' do
15
+ it 'defaults to ""' do
16
+ expect(IbanCalculator.user).to eq('')
17
+ end
18
+
19
+ it 'allows specifying it' do
20
+ IbanCalculator.user = 'test'
21
+ expect(IbanCalculator.user).to eq('test')
22
+ IbanCalculator.user = ''
23
+ end
24
+ end
25
+
26
+ describe '.password' do
27
+ it 'defaults to ""' do
28
+ expect(IbanCalculator.password).to eq('')
29
+ end
30
+
31
+ it 'allows specifying it' do
32
+ IbanCalculator.password = 'test'
33
+ expect(IbanCalculator.password).to eq('test')
34
+ IbanCalculator.password = ''
35
+ end
36
+ end
37
+
38
+ describe '.logger' do
39
+ it 'defaults to a logger instance' do
40
+ expect(IbanCalculator.logger).to be_instance_of(Logger)
41
+ end
42
+
43
+ it 'allows specifying it' do
44
+ old_logger = IbanCalculator.logger
45
+ logger = Logger.new(STDERR)
46
+ IbanCalculator.logger = logger
47
+ expect(IbanCalculator.logger).to eql(logger)
48
+ IbanCalculator.logger = old_logger
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,55 @@
1
+ describe IbanCalculator::InvalidData do
2
+ subject { described_class.new('', 128) }
3
+
4
+ describe '#resolve_error_code' do
5
+ it 'handles single errors' do
6
+ expect(subject.resolve_error_code(128)).to eq(account_number: [:checksum_failed])
7
+ end
8
+
9
+ it 'can combine multiple errors' do
10
+ expect(subject.resolve_error_code(128 + 256)).to eq(account_number: [:checksum_failed], bank_code: [:not_found])
11
+ end
12
+
13
+ it 'can combine multiple errors of same attribute' do
14
+ expect(subject.resolve_error_code(128 + 512)).to eq(account_number: [:checksum_failed, :invalid_length])
15
+ end
16
+
17
+ it 'can combine multiple errors of same attribute' do
18
+ expect(subject.resolve_error_code(512)).to eq(account_number: [:invalid_length])
19
+ end
20
+ end
21
+
22
+ describe '#error_codes' do
23
+ it 'ignores zeros' do
24
+ expect(subject.error_codes(0)).to eq([])
25
+ end
26
+
27
+ it 'detects unique values' do
28
+ expect(subject.error_codes(1)).to eq([1])
29
+ end
30
+
31
+ it 'detects compounded values' do
32
+ expect(subject.error_codes(3)).to eq([1, 2])
33
+ end
34
+
35
+ it 'detects 512' do
36
+ expect(subject.error_codes(512)).to eq([512])
37
+ end
38
+
39
+ it 'detects compounded values up to 8192' do
40
+ expect(subject.error_codes(8193)).to eq([1, 8192])
41
+ end
42
+ end
43
+
44
+ describe '#known_error_codes' do
45
+ it 'detects 512' do
46
+ expect(subject.known_error_codes(512)).to eq([512])
47
+ end
48
+ end
49
+
50
+ describe '#error' do
51
+ it 'sets error on object' do
52
+ expect(described_class.new('test', 512).errors).to eq(account_number: [:invalid_length])
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,25 @@
1
+ require 'iban_calculator'
2
+
3
+ RSpec.configure do |config|
4
+ config.filter_run :focus
5
+ config.run_all_when_everything_filtered = true
6
+
7
+ if config.files_to_run.one?
8
+ config.default_formatter = 'doc'
9
+ end
10
+
11
+ config.profile_examples = 3
12
+
13
+ config.order = :random
14
+
15
+ Kernel.srand config.seed
16
+
17
+ config.expect_with :rspec do |expectations|
18
+ expectations.syntax = :expect
19
+ end
20
+
21
+ config.mock_with :rspec do |mocks|
22
+ mocks.syntax = :expect
23
+ mocks.verify_partial_doubles = true
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: iban_calculator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Maximilian Schulz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: savon
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3'
83
+ description: At the moment the gem is just a wrapper for the ibanrechner.de API.
84
+ email:
85
+ - m.schulz@kulturfluss.de
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - iban_calculator.gemspec
97
+ - lib/iban_calculator.rb
98
+ - lib/iban_calculator/iban_bic.rb
99
+ - lib/iban_calculator/invalid_data.rb
100
+ - lib/iban_calculator/version.rb
101
+ - spec/iban_bic_spec.rb
102
+ - spec/iban_calculator_spec.rb
103
+ - spec/invalid_data_spec.rb
104
+ - spec/spec_helper.rb
105
+ homepage: https://github.com/railslove/iban_calculator
106
+ licenses:
107
+ - MIT
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.2.2
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: Calculate IBAN and BIC for countries of Single European Payments Area (SEPA).
129
+ test_files:
130
+ - spec/iban_bic_spec.rb
131
+ - spec/iban_calculator_spec.rb
132
+ - spec/invalid_data_spec.rb
133
+ - spec/spec_helper.rb
134
+ has_rdoc: