banktools-se 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in bank-tools-se.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,6 @@
1
+ guard 'rspec', :version => 2, :cli => "--color" do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/banktools-se/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec" }
5
+ watch('spec/spec_helper.rb') { "spec" }
6
+ end
data/README.markdown ADDED
@@ -0,0 +1,108 @@
1
+ # Swedish bank tools
2
+
3
+ Ruby gem to validate, normalize/prettify and to some extent interpret
4
+
5
+ * Swedish bank account numbers
6
+ * Swedish plusgiro numbers
7
+ * Swedish bankgiro numbers
8
+
9
+ Inspired by [iulianu/iban-tools](https://github.com/iulianu/iban-tools). Please consider contributing gems for your country.
10
+
11
+
12
+ ## Installation
13
+
14
+ With Bundler for e.g. Ruby on Rails, add this to your `Gemfile`:
15
+
16
+ gem 'banktools-se', :git => 'git://github.com/barsoom/banktools-se.git'
17
+
18
+ and run
19
+
20
+ bundle
21
+
22
+ to install it.
23
+
24
+
25
+ ## Usage
26
+
27
+ # Bankgiro
28
+
29
+ valid_account = BankTools::SE::Bankgiro.new(" 5402968 1 ")
30
+ valid_account.valid? # => true
31
+ valid_account.errors # => []
32
+ valid_account.normalize # => "5402-9681"
33
+
34
+ bad_account = BankTools::SE::Bankgiro.new(" 1X ")
35
+ bad_account.valid? # => false
36
+ bad_account.errors # => [ :too_short, :invalid_characters, :bad_checksum ]
37
+ bad_account.normalize # => " 1 "
38
+
39
+ # 90-konto
40
+ fundraising_account = BankTools::SE::Bankgiro.new("902-0033")
41
+ fundraising_account.fundraising? # => true
42
+
43
+
44
+ # Plusgiro
45
+
46
+ valid_account = BankTools::SE::Plusgiro.new("2865434")
47
+ valid_account.valid? # => true
48
+ valid_account.errors # => []
49
+ valid_account.normalize # => "28 65 53-4"
50
+
51
+ bad_account = BankTools::SE::Plusgiro.new(" 1X ")
52
+ bad_account.valid? # => false
53
+ bad_account.errors # => [ :too_short, :invalid_characters, :bad_checksum ]
54
+ bad_account.normalize # => " 1 "
55
+
56
+ # 90-konto
57
+ fundraising_account = BankTools::SE::Plusgiro.new("90 20 03-3")
58
+ fundraising_account.fundraising? # => true
59
+
60
+
61
+ # Bank account
62
+
63
+ valid_account = BankTools::SE::Account.new("1100-0000000")
64
+ valid_account.valid? # => true
65
+ valid_account.errors # => []
66
+ valid_account.bank # => "Nordea"
67
+ valid_account.normalize # => "11000000007"
68
+
69
+ bad_account = BankTools::SE::Account.new(" 0000-0000000X ")
70
+ bad_account.valid? # => false
71
+ bad_account.errors # => [ :invalid_characters, :unknown_clearing_number ]
72
+ bad_account.bank # => nil
73
+ bad_account.normalize # => " 0000-0000000X "
74
+
75
+
76
+ ## TODO
77
+
78
+ Possible improvements to make:
79
+
80
+ * Handle [Swedbank zerofill](http://www.danskebank.se/sv-se/eBanking-content/text-pages/Pages/Bankliste2.aspx).
81
+ * Handle [Sparbanken zerofill](http://www.danskebank.se/sv-se/eBanking-content/text-pages/Pages/Bankliste2.aspx).
82
+ * Look into just what bank account numbers need Luhn validation of which part.
83
+
84
+
85
+ ## Credits and license
86
+
87
+ By [Henrik Nyh](http://henrik.nyh.se/) for [Barsoom](http://barsoom.se) under the MIT license:
88
+
89
+ > Copyright (c) 2011 Barsoom AB
90
+ >
91
+ > Permission is hereby granted, free of charge, to any person obtaining a copy
92
+ > of this software and associated documentation files (the "Software"), to deal
93
+ > in the Software without restriction, including without limitation the rights
94
+ > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
95
+ > copies of the Software, and to permit persons to whom the Software is
96
+ > furnished to do so, subject to the following conditions:
97
+ >
98
+ > The above copyright notice and this permission notice shall be included in
99
+ > all copies or substantial portions of the Software.
100
+ >
101
+ > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
102
+ > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
103
+ > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
104
+ > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
105
+ > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
106
+ > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
107
+ > THE SOFTWARE.
108
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "banktools-se/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "banktools-se"
7
+ s.version = BankTools::SE::VERSION
8
+ s.authors = ["Henrik Nyh"]
9
+ s.email = ["henrik@barsoom.se"]
10
+ s.homepage = ""
11
+ s.summary = %q{Validate and normalize Swedish bank account numbers, plusgiro and bankgiro.}
12
+
13
+ s.rubyforge_project = "banktools-se"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_development_dependency "rspec"
21
+ s.add_development_dependency "guard"
22
+ s.add_development_dependency "guard-rspec"
23
+ end
@@ -0,0 +1,161 @@
1
+ # encoding: utf-8
2
+
3
+ module BankTools
4
+ module SE
5
+ class Account
6
+
7
+ # http://sv.wikipedia.org/wiki/Lista_%C3%B6ver_clearingnummer_till_svenska_banker
8
+ # Max lengths from
9
+ # http://www.danskebank.se/sv-se/eBanking-content/text-pages/Pages/Bankliste2.aspx
10
+ # Min lengths are educated guesses based on the above and
11
+ # http://sv.wikipedia.org/wiki/Bankkonto
12
+ # When it's uncertain, let's error on the side of allowing too much.
13
+ # 1..99 means we have no idea.
14
+
15
+ DEFAULT_SERIAL_NUMBER_LENGTH = 7
16
+
17
+ CLEARING_NUMBER_MAP = {
18
+ 1100..1199 => { :name => "Nordea" },
19
+ 1200..1399 => { :name => "Danske Bank" },
20
+ 1400..2099 => { :name => "Nordea" },
21
+ 2300..2309 => { :name => "JP Nordiska", :serial_number_length => 1..99 },
22
+ 2310..2310 => { :name => "Ålandsbanken" },
23
+ 2311..2399 => { :name => "JP Nordiska", :serial_number_length => 1..99 },
24
+ 2950..2950 => { :name => "Sambox", :serial_number_length => 1..99 },
25
+ 3000..3299 => { :name => "Nordea" },
26
+ 3300..3300 => { :name => "Nordea", :serial_number_length => 10, :luhn_for_serial => true }, # Personkonto.
27
+ 3301..3399 => { :name => "Nordea" },
28
+ 3400..3409 => { :name => "Länsförsäkringar Bank" },
29
+ 3410..3781 => { :name => "Nordea" },
30
+ 3782..3782 => { :name => "Nordea", :serial_number_length => 10, :luhn_for_serial => true }, # Personkonto.
31
+ 3783..4999 => { :name => "Nordea" },
32
+ 5000..5999 => { :name => "SEB" },
33
+ 6000..6999 => { :name => "Handelsbanken", :serial_number_length => 9 },
34
+ 7000..7120 => { :name => "Swedbank" },
35
+ 7121..7122 => { :name => "Sparbanken i Enköping", :serial_number_length => 7..10 }, # 7? 10? Who knows.
36
+ 7123..7999 => { :name => "Swedbank" },
37
+ 8000..8999 => { :name => "Swedbank och fristående Sparbanker", :serial_number_length => 10, :checksum_for_clearing => true },
38
+ 9020..9029 => { :name => "Länsförsäkringar Bank" },
39
+ 9040..9049 => { :name => "Citibank" },
40
+ 9050..9059 => { :name => "HSB Bank", :serial_number_length => 1..99 },
41
+ 9060..9069 => { :name => "Länsförsäkringar Bank" },
42
+ 9080..9080 => { :name => "Calyon Bank", :serial_number_length => 1..99 },
43
+ 9090..9099 => { :name => "ABN AMRO", :serial_number_length => 1..99 },
44
+ 9100..9100 => { :name => "Nordnet Bank" },
45
+ 9120..9124 => { :name => "SEB" },
46
+ 9130..9149 => { :name => "SEB" },
47
+ 9150..9169 => { :name => "Skandiabanken" },
48
+ 9170..9179 => { :name => "Ikano Bank" },
49
+ 9180..9189 => { :name => "Danske Bank" },
50
+ 9190..9199 => { :name => "Den Norske Bank" },
51
+ 9200..9209 => { :name => "Stadshypotek Bank", :serial_number_length => 1..99 },
52
+ 9230..9230 => { :name => "Bank2" },
53
+ 9231..9239 => { :name => "SalusAnsvar Bank", :serial_number_length => 1..99 },
54
+ 9260..9269 => { :name => "Gjensidige NOR Sparebank", :serial_number_length => 1..99 },
55
+ 9270..9279 => { :name => "ICA Banken" },
56
+ 9280..9289 => { :name => "Resurs Bank" },
57
+ 9290..9299 => { :name => "Coop Bank", :serial_number_length => 1..99 },
58
+ 9300..9349 => { :name => "Sparbanken Öresund", :serial_number_length => 10 },
59
+ 9400..9400 => { :name => "Forex Bank" },
60
+ 9460..9460 => { :name => "GE Money Bank" },
61
+ 9469..9469 => { :name => "GE Money Bank" },
62
+ 9500..9547 => { :name => "Plusgirot Bank", :serial_number_length => 10 },
63
+ 9548..9548 => { :name => "Ekobanken", :serial_number_length => 1..99 },
64
+ 9549..9549 => { :name => "JAK Medlemsbank", :serial_number_length => 1..99 },
65
+ 9550..9550 => { :name => "Avanza Bank" },
66
+ 9960..9969 => { :name => "Plusgirot Bank", :serial_number_length => 10 },
67
+ }
68
+
69
+ attr_reader :number
70
+
71
+ def initialize(number)
72
+ @number = number
73
+ end
74
+
75
+ def valid?
76
+ errors.empty?
77
+ end
78
+
79
+ def errors
80
+ errors = []
81
+
82
+ errors << :too_short if serial_number.length < min_length
83
+ errors << :too_long if serial_number.length > max_length
84
+ errors << :invalid_characters if number.to_s.match(/[^0-9 -]/)
85
+
86
+ if luhn_for_serial?
87
+ errors << :bad_checksum unless BankTools::SE::Utils.valid_luhn?(serial_number)
88
+ end
89
+
90
+ errors << :unknown_clearing_number unless bank
91
+
92
+ errors
93
+ end
94
+
95
+ def normalize
96
+ if valid?
97
+ [ clearing_number, serial_number ].join("-")
98
+ else
99
+ number
100
+ end
101
+ end
102
+
103
+ def bank
104
+ bank_data[:name]
105
+ end
106
+
107
+ def clearing_number
108
+ digits[0,4]
109
+ end
110
+
111
+ def serial_number
112
+ value = digits[4..-1] || ""
113
+ if checksum_for_clearing? && value.length == max_length
114
+ value[1..-1]
115
+ else
116
+ value
117
+ end
118
+ end
119
+
120
+ private
121
+
122
+ def bank_data
123
+ number = clearing_number.to_i
124
+ _, found_data = CLEARING_NUMBER_MAP.find do |interval, data|
125
+ interval.include?(number)
126
+ end
127
+ found_data || {}
128
+ end
129
+
130
+ def min_length
131
+ if bank_data
132
+ Array(bank_data[:serial_number_length] || DEFAULT_SERIAL_NUMBER_LENGTH).first
133
+ else
134
+ 0
135
+ end
136
+ end
137
+
138
+ def max_length
139
+ if bank_data
140
+ Array(bank_data[:serial_number_length] || DEFAULT_SERIAL_NUMBER_LENGTH).last +
141
+ (checksum_for_clearing? ? 1 : 0)
142
+ else
143
+ 1/0.0 # Infinity.
144
+ end
145
+ end
146
+
147
+ def luhn_for_serial?
148
+ bank_data[:luhn_for_serial]
149
+ end
150
+
151
+ def checksum_for_clearing?
152
+ bank_data[:checksum_for_clearing]
153
+ end
154
+
155
+ def digits
156
+ number.to_s.gsub(/\D/, '')
157
+ end
158
+
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,48 @@
1
+ module BankTools
2
+ module SE
3
+ class Bankgiro
4
+
5
+ # http://sv.wikipedia.org/wiki/Bankgirot#Bankgironummer
6
+
7
+ attr_reader :number
8
+
9
+ def initialize(number)
10
+ @number = number
11
+ end
12
+
13
+ def valid?
14
+ errors.empty?
15
+ end
16
+
17
+ def errors
18
+ errors = []
19
+
20
+ errors << :too_short if digits.length < 7
21
+ errors << :too_long if digits.length > 8
22
+ errors << :invalid_characters if number.to_s.match(/[^0-9 -]/)
23
+ errors << :bad_checksum unless BankTools::SE::Utils.valid_luhn?(number)
24
+
25
+ errors
26
+ end
27
+
28
+ def normalize
29
+ if valid?
30
+ digits.split(/(\d{4})$/).join("-")
31
+ else
32
+ number
33
+ end
34
+ end
35
+
36
+ def fundraising?
37
+ valid? && digits.match(/^90[0-4]/)
38
+ end
39
+
40
+ private
41
+
42
+ def digits
43
+ number.to_s.gsub(/\D/, '')
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,53 @@
1
+ module BankTools
2
+ module SE
3
+ class Plusgiro
4
+
5
+ # Could sadly not find anything more authoritative than
6
+ # http://pellesoft.se/communicate/forum/view.aspx?msgid=267449&forumid=63&sum=0
7
+
8
+ attr_reader :number
9
+
10
+ def initialize(number)
11
+ @number = number
12
+ end
13
+
14
+ def valid?
15
+ errors.empty?
16
+ end
17
+
18
+ def errors
19
+ errors = []
20
+
21
+ errors << :too_short if digits.length < 2
22
+ errors << :too_long if digits.length > 8
23
+ errors << :invalid_characters if number.to_s.match(/[^0-9 -]/)
24
+ errors << :bad_checksum unless BankTools::SE::Utils.valid_luhn?(number)
25
+
26
+ errors
27
+ end
28
+
29
+ def normalize
30
+ if valid?
31
+ pre, pairs, post = digits.split(/(\d{2}*)(\d)$/)
32
+ pairs = pairs.split(/(\d\d)/).reject { |x| x.empty? }
33
+ [ pre, pairs.join(" "), "-", post ].join
34
+ else
35
+ number
36
+ end
37
+ end
38
+
39
+ # http://www.plusgirot.se/Om+PlusGirot/90-konton/508552.html
40
+ # http://www.insamlingskontroll.se/
41
+ def fundraising?
42
+ valid? && digits.match(/^90\d{5}$/)
43
+ end
44
+
45
+ private
46
+
47
+ def digits
48
+ number.to_s.gsub(/\D/, '')
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,19 @@
1
+ module BankTools
2
+ module SE
3
+ module Utils
4
+
5
+ # Based on http://blog.internautdesign.com/2007/4/18/ruby-luhn-check-aka-mod-10-formula
6
+ require "enumerator"
7
+ def self.valid_luhn?(number)
8
+ digits = number.to_s.scan(/\d/).reverse.map { |x| x.to_i }
9
+ digits = digits.enum_with_index.map { |d, i|
10
+ d *= 2 if i.odd?
11
+ d > 9 ? d - 9 : d
12
+ }
13
+ sum = digits.inject(0) { |m, x| m + x }
14
+ sum % 10 == 0
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ module BankTools
2
+ module SE
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ require "banktools-se/version"
2
+ require "banktools-se/utils"
3
+ require "banktools-se/bankgiro"
4
+ require "banktools-se/plusgiro"
5
+ require "banktools-se/account"
@@ -0,0 +1,176 @@
1
+ # encoding: utf-8
2
+
3
+ require "spec_helper"
4
+ require "banktools-se"
5
+
6
+ describe BankTools::SE::Account do
7
+
8
+ it "should initialize" do
9
+ BankTools::SE::Account.new("foo").should be_a(BankTools::SE::Account)
10
+ end
11
+
12
+ describe "#valid?" do
13
+
14
+ it "should be true with no errors" do
15
+ account = BankTools::SE::Account.new("foo")
16
+ account.stub!(:errors).and_return([])
17
+ account.should be_valid
18
+ end
19
+
20
+ it "should be false with errors" do
21
+ account = BankTools::SE::Account.new("foo")
22
+ account.stub!(:errors).and_return([:error])
23
+ account.should_not be_valid
24
+ end
25
+
26
+ end
27
+
28
+ describe "#errors" do
29
+ [
30
+ "1100-0000000", # Nordea.
31
+ "1155-0000000", # Nordea.
32
+ "1199-0000000", # Nordea.
33
+ "1200-0000000", # Danske Bank.
34
+ "1400-0000000", # Nordea.
35
+ "2300-00", # JP Nordiska.
36
+ "2310-0000000", # Ålandsbanken.
37
+ "2311-00", # JP Nordiska.
38
+ "2950-00", # Sambox.
39
+ "3000-0000000", # Nordea.
40
+ "3300-800928-6249", # Nordea personkonto.
41
+ "3301-0000000", # Nordea.
42
+ "3400-0000000", # Länsförsäkringar Bank.
43
+ "3410-0000000", # Nordea.
44
+ "3782-800928-6249", # Nordea personkonto.
45
+ "3783-0000000", # Nordea.
46
+ "5000-0000000", # SEB.
47
+ "6000-000000000", # Handelsbanken.
48
+ "7000-0000000", # Swedbank.
49
+ "7121-0000000", # Sparbanken i Enköping.
50
+ "7123-0000000", # Swedbank.
51
+ "8000-0000000000", # Swedbank/Sparbanker.
52
+ "8000-2-0000000000", # Swedbank/Sparbanker with clearing number checksum.
53
+ "9020-0000000", # Länsförsäkringar Bank.
54
+ "9040-0000000", # Citibank.
55
+ "9050-00", # HSB Bank.
56
+ "9060-0000000", # Länsförsäkringar Bank.
57
+ "9080-00", # Calyon Bank.
58
+ "9090-00", # ABN AMBRO.
59
+ "9100-0000000", # Nordnet Bank.
60
+ "9120-0000000", # SEB.
61
+ "9130-0000000", # SEB.
62
+ "9150-0000000", # Skandiabanken.
63
+ "9170-0000000", # Ikano Bank.
64
+ "9180-0000000", # Danske Bank.
65
+ "9190-0000000", # Den Norske Bank.
66
+ "9200-00", # Stadshypotek Bank.
67
+ "9230-0000000", # Bank2.
68
+ "9231-00", # SalusAnsvar Bank.
69
+ "9260-00", # Gjensidige NOR Sparebank.
70
+ "9270-0000000", # ICA Banken.
71
+ "9280-0000000", # Resurs Bank.
72
+ "9290-00", # Coop Bank.
73
+ "9300-0000000000", # Sparbanken Öresund.
74
+ "9400-0000000", # Forex Bank.
75
+ "9460-0000000", # GE Money Bank.
76
+ "9469-0000000", # GE Money Bank.
77
+ "9500-0000000000", # Plusgirot Bank.
78
+ "9548-00", # Ekobanken.
79
+ "9549-00", # JAK Medlemsbank.
80
+ "9550-0000000", # Avanza Bank.
81
+ "9960-0000000000", # Plusgirot Bank.
82
+
83
+ ].each do |number|
84
+ it "should be empty for a valid number like #{number}" do
85
+ BankTools::SE::Account.new(number).errors.should == []
86
+ end
87
+ end
88
+
89
+ it "should include :too_short for numbers shorter than the bank allows" do
90
+ BankTools::SE::Account.new("11007").errors.should include(:too_short)
91
+ end
92
+
93
+ it "should include :too_long for numbers longer than the bank allows" do
94
+ BankTools::SE::Account.new("1100000000007").errors.should include(:too_long)
95
+ end
96
+
97
+ it "should not include :too_long for Swedbank/Sparbanker numbers with clearing checksum" do
98
+ BankTools::SE::Account.new("8000-2-0000000000").errors.should_not include(:too_long)
99
+ end
100
+
101
+ it "should include :invalid_characters for numbers with other character than digits, spaces and dashes" do
102
+ BankTools::SE::Account.new("1 2-3X").errors.should include(:invalid_characters)
103
+ BankTools::SE::Account.new("1 2-3").errors.should_not include(:invalid_characters)
104
+ end
105
+
106
+ it "should include :bad_checksum for Nordea personkonto if the serial Luhn/mod 10 checksum is incorrect" do
107
+ BankTools::SE::Utils.valid_luhn?("800928-6249").should be_true
108
+ BankTools::SE::Utils.valid_luhn?("3300-800928-6249").should be_false
109
+ BankTools::SE::Account.new("3300-800928-6249").errors.should_not include(:bad_checksum)
110
+ end
111
+
112
+ it "should include :unknown_clearing_number if the clearing number is unknown" do
113
+ BankTools::SE::Account.new("10000000009").errors.should include(:unknown_clearing_number)
114
+ BankTools::SE::Account.new("11000000007").errors.should_not include(:unknown_clearing_number)
115
+ end
116
+
117
+ end
118
+
119
+ describe "#bank" do
120
+
121
+ it "should return the bank for the current clearing number" do
122
+ BankTools::SE::Account.new("11000000007").bank.should == "Nordea"
123
+ BankTools::SE::Account.new("11550000001").bank.should == "Nordea"
124
+ BankTools::SE::Account.new("11990000009").bank.should == "Nordea"
125
+ BankTools::SE::Account.new("12000000005").bank.should == "Danske Bank"
126
+ end
127
+
128
+ it "should return nil for unknown clearing numbers" do
129
+ BankTools::SE::Account.new("10000000009").bank.should be_nil
130
+ end
131
+
132
+ end
133
+
134
+ describe "#clearing_number" do
135
+
136
+ it "should be the first four digits" do
137
+ BankTools::SE::Account.new("12345678").clearing_number.should == "1234"
138
+ end
139
+
140
+ end
141
+
142
+ describe "#serial_number" do
143
+
144
+ it "should be the digits after the first four digits" do
145
+ BankTools::SE::Account.new("12345678").serial_number.should == "5678"
146
+ end
147
+
148
+ it "should be the empty string if there aren't enough numbers" do
149
+ BankTools::SE::Account.new("12").serial_number.should == ""
150
+ end
151
+
152
+ it "should exclude any Swedbank/Sparbanker clearing checksum" do
153
+ BankTools::SE::Account.new("8000-2-0000000000").serial_number.should == "0000000000"
154
+ BankTools::SE::Account.new("8000-0000000000").serial_number.should == "0000000000"
155
+ end
156
+
157
+ end
158
+
159
+ describe "#normalize" do
160
+
161
+ it "should normalize to clearing number dash serial number" do
162
+ account = BankTools::SE::Account.new("11000000007").normalize.should == "1100-0000007"
163
+ end
164
+
165
+ it "should remove any Swedbank/Sparbanker clearing checksum" do
166
+ BankTools::SE::Account.new("8000-2-0000000000").normalize.should == "8000-0000000000"
167
+ BankTools::SE::Account.new("8000-0000000000").normalize.should == "8000-0000000000"
168
+ end
169
+
170
+ it "should not attempt to normalize invalid numbers" do
171
+ account = BankTools::SE::Account.new(" 1-2-3 ").normalize.should == " 1-2-3 "
172
+ end
173
+
174
+ end
175
+
176
+ end
@@ -0,0 +1,95 @@
1
+ require "spec_helper"
2
+ require "banktools-se"
3
+
4
+ describe BankTools::SE::Bankgiro do
5
+
6
+ it "should initialize" do
7
+ BankTools::SE::Bankgiro.new("foo").should be_a(BankTools::SE::Bankgiro)
8
+ end
9
+
10
+ describe "#valid?" do
11
+
12
+ it "should be true with no errors" do
13
+ account = BankTools::SE::Bankgiro.new("foo")
14
+ account.stub!(:errors).and_return([])
15
+ account.should be_valid
16
+ end
17
+
18
+ it "should be false with errors" do
19
+ account = BankTools::SE::Bankgiro.new("foo")
20
+ account.stub!(:errors).and_return([:error])
21
+ account.should_not be_valid
22
+ end
23
+
24
+ end
25
+
26
+ describe "#errors" do
27
+ # From http://www.carnegie.se/sv/Carnegie-fonder/Kopa-fonder/Bankgironummer/
28
+ [
29
+ "5402-9681",
30
+ "297-3675",
31
+ "640-5070",
32
+ ].each do |number|
33
+ it "should be empty for a valid number like #{number}" do
34
+ BankTools::SE::Bankgiro.new(number).errors.should be_empty
35
+ end
36
+ end
37
+
38
+ it "should include :too_short for numbers shorter than 7 digits" do
39
+ BankTools::SE::Bankgiro.new(nil).errors.should include(:too_short)
40
+ BankTools::SE::Bankgiro.new("").errors.should include(:too_short)
41
+ BankTools::SE::Bankgiro.new("54-0296").errors.should include(:too_short)
42
+ BankTools::SE::Bankgiro.new("54---------0296").errors.should include(:too_short)
43
+ end
44
+
45
+ it "should include :too_long for numbers longer than 8 digits" do
46
+ BankTools::SE::Bankgiro.new("5402-96810").errors.should include(:too_long)
47
+ end
48
+
49
+ it "should include :invalid_characters for numbers with other character than digits, spaces and dashes" do
50
+ BankTools::SE::Bankgiro.new("5402-9681X").errors.should include(:invalid_characters)
51
+ BankTools::SE::Bankgiro.new(" 5 4 0 2 - 9 6 8 1 ").errors.should_not include(:invalid_characters)
52
+ end
53
+
54
+ it "should include :bad_checksum if the Luhn/mod 10 checksum is incorrect" do
55
+ BankTools::SE::Bankgiro.new("5402-9682").errors.should include(:bad_checksum)
56
+ end
57
+
58
+ end
59
+
60
+ describe "#normalize" do
61
+
62
+ it "should normalize 7-digit numbers to NNN-NNNN" do
63
+ account = BankTools::SE::Bankgiro.new(" 6-40 - 5070")
64
+ account.normalize.should == "640-5070"
65
+ end
66
+
67
+ it "should normalize 8-digit numbers to NNNN-NNNN" do
68
+ account = BankTools::SE::Bankgiro.new(" 5-4-0-2-9-6- 81- ")
69
+ account.normalize.should == "5402-9681"
70
+ end
71
+
72
+ it "should not attempt to normalize invalid numbers" do
73
+ account = BankTools::SE::Bankgiro.new(" 1-2-3 ")
74
+ account.normalize.should == " 1-2-3 "
75
+ end
76
+
77
+ end
78
+
79
+ describe "#fundraising? (90-konto)" do
80
+
81
+ it "should be true for the number series 900-nnnn to 904-nnnn" do
82
+ BankTools::SE::Bankgiro.new("902-0033").should be_fundraising
83
+ end
84
+
85
+ it "should be false for invalid numbers in the right series" do
86
+ BankTools::SE::Bankgiro.new("902-0034").should_not be_fundraising
87
+ end
88
+
89
+ it "should be false for numbers outside the right series" do
90
+ BankTools::SE::Bankgiro.new("5402-9681").should_not be_fundraising
91
+ end
92
+
93
+ end
94
+
95
+ end
@@ -0,0 +1,100 @@
1
+ require "spec_helper"
2
+ require "banktools-se"
3
+
4
+ describe BankTools::SE::Plusgiro do
5
+
6
+ it "should initialize" do
7
+ BankTools::SE::Plusgiro.new("foo").should be_a(BankTools::SE::Plusgiro)
8
+ end
9
+
10
+ describe "#valid?" do
11
+
12
+ it "should be true with no errors" do
13
+ account = BankTools::SE::Plusgiro.new("foo")
14
+ account.stub!(:errors).and_return([])
15
+ account.should be_valid
16
+ end
17
+
18
+ it "should be false with errors" do
19
+ account = BankTools::SE::Plusgiro.new("foo")
20
+ account.stub!(:errors).and_return([:error])
21
+ account.should_not be_valid
22
+ end
23
+
24
+ end
25
+
26
+ describe "#errors" do
27
+ [
28
+ "28 65 43-4", # IKEA
29
+ "410 54 68-5", # IKEA
30
+ "4-2", # Sveriges riksbank
31
+ ].each do |number|
32
+ it "should be empty for a valid number like #{number}" do
33
+ BankTools::SE::Plusgiro.new(number).errors.should be_empty
34
+ end
35
+ end
36
+
37
+ it "should include :too_short for numbers shorter than 2 digits" do
38
+ BankTools::SE::Plusgiro.new(nil).errors.should include(:too_short)
39
+ BankTools::SE::Plusgiro.new("").errors.should include(:too_short)
40
+ BankTools::SE::Plusgiro.new("1").errors.should include(:too_short)
41
+ BankTools::SE::Plusgiro.new("1---------").errors.should include(:too_short)
42
+ end
43
+
44
+ it "should include :too_long for numbers longer than 8 digits" do
45
+ BankTools::SE::Plusgiro.new("410 54 68-51").errors.should include(:too_long)
46
+ end
47
+
48
+ it "should include :invalid_characters for numbers with other character than digits, spaces and dashes" do
49
+ BankTools::SE::Plusgiro.new("410 54 68-5X").errors.should include(:invalid_characters)
50
+ BankTools::SE::Plusgiro.new("4 1 0 5 4 6 8 - 5 ").errors.should_not include(:invalid_characters)
51
+ end
52
+
53
+ it "should include :bad_checksum if the Luhn/mod 10 checksum is incorrect" do
54
+ BankTools::SE::Plusgiro.new("410 54 68-6").errors.should include(:bad_checksum)
55
+ end
56
+
57
+ end
58
+
59
+ describe "#normalize" do
60
+
61
+ it "should normalize short numbers to the format N-N" do
62
+ account = BankTools::SE::Plusgiro.new(" 4 - 2")
63
+ account.normalize.should == "4-2"
64
+ end
65
+
66
+ it "should normalize odd-length numbers to the format NN NN NN-N" do
67
+ account = BankTools::SE::Plusgiro.new("2865434")
68
+ account.normalize.should == "28 65 43-4"
69
+ end
70
+
71
+ it "should normalize even-length numbers to the format NNN NN NN-N" do
72
+ account = BankTools::SE::Plusgiro.new("41054685")
73
+ account.normalize.should == "410 54 68-5"
74
+ end
75
+
76
+ it "should not attempt to normalize invalid numbers" do
77
+ account = BankTools::SE::Plusgiro.new(" 1-2-3 ")
78
+ account.normalize.should == " 1-2-3 "
79
+ end
80
+
81
+ end
82
+
83
+ describe "#fundraising? (90-konto)" do
84
+
85
+ it "should be true for the number series 90-nnnn" do
86
+ BankTools::SE::Plusgiro.new("90 20 03-3").should be_fundraising
87
+ end
88
+
89
+ it "should be false for invalid numbers in the right series" do
90
+ BankTools::SE::Plusgiro.new("90 20 03-4").should_not be_fundraising
91
+ end
92
+
93
+ it "should be false for numbers outside the right series" do
94
+ BankTools::SE::Plusgiro.new("4-2").should_not be_fundraising
95
+ end
96
+
97
+ end
98
+
99
+
100
+ end
@@ -0,0 +1,5 @@
1
+ RSpec.configure do |config|
2
+ config.treat_symbols_as_metadata_keys_with_true_values = true
3
+ config.filter_run :focus => true
4
+ config.run_all_when_everything_filtered = true
5
+ end
@@ -0,0 +1,36 @@
1
+ require "spec_helper"
2
+ require "banktools-se/utils"
3
+
4
+ describe BankTools::SE::Utils, "valid_luhn?" do
5
+
6
+ [
7
+ "00",
8
+ "18",
9
+ "26",
10
+ "34",
11
+ "42",
12
+ "59",
13
+ "67",
14
+ "75",
15
+ "83",
16
+ "91",
17
+ "109",
18
+ "117",
19
+ "5402-9681",
20
+ ].each do |number|
21
+ it "should allow a valid number like #{number}" do
22
+ BankTools::SE::Utils.valid_luhn?(number).should be_true
23
+ end
24
+ end
25
+
26
+ [
27
+ "01",
28
+ "118",
29
+ "5402-9682",
30
+ ].each do |number|
31
+ it "should disallow an invalid number like #{number}" do
32
+ BankTools::SE::Utils.valid_luhn?(number).should be_false
33
+ end
34
+ end
35
+
36
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: banktools-se
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Henrik Nyh
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-10-12 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rspec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: guard
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: guard-rspec
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
63
+ description:
64
+ email:
65
+ - henrik@barsoom.se
66
+ executables: []
67
+
68
+ extensions: []
69
+
70
+ extra_rdoc_files: []
71
+
72
+ files:
73
+ - .gitignore
74
+ - Gemfile
75
+ - Guardfile
76
+ - README.markdown
77
+ - Rakefile
78
+ - banktools-se.gemspec
79
+ - lib/banktools-se.rb
80
+ - lib/banktools-se/account.rb
81
+ - lib/banktools-se/bankgiro.rb
82
+ - lib/banktools-se/plusgiro.rb
83
+ - lib/banktools-se/utils.rb
84
+ - lib/banktools-se/version.rb
85
+ - spec/account_spec.rb
86
+ - spec/bankgiro_spec.rb
87
+ - spec/plusgiro_spec.rb
88
+ - spec/spec_helper.rb
89
+ - spec/utils_spec.rb
90
+ has_rdoc: true
91
+ homepage: ""
92
+ licenses: []
93
+
94
+ post_install_message:
95
+ rdoc_options: []
96
+
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ hash: 3
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ hash: 3
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ requirements: []
118
+
119
+ rubyforge_project: banktools-se
120
+ rubygems_version: 1.5.3
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: Validate and normalize Swedish bank account numbers, plusgiro and bankgiro.
124
+ test_files:
125
+ - spec/account_spec.rb
126
+ - spec/bankgiro_spec.rb
127
+ - spec/plusgiro_spec.rb
128
+ - spec/spec_helper.rb
129
+ - spec/utils_spec.rb