uk_account_validator 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rubocop.yml +11 -0
- data/.travis.yml +13 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +23 -0
- data/README.md +56 -0
- data/Rakefile +2 -0
- data/data/scsubtab.txt +21 -0
- data/data/valacdos.txt +987 -0
- data/features/exceptions.feature +49 -0
- data/features/modulus10.feature +18 -0
- data/features/modulus11.feature +15 -0
- data/features/modulus_weight.feature +26 -0
- data/features/modulus_weights_table.feature +14 -0
- data/features/step_definitions/basics.rb +23 -0
- data/features/step_definitions/modulus_weight.rb +7 -0
- data/features/step_definitions/modulus_weights_table.rb +13 -0
- data/features/support/env.rb +2 -0
- data/features/two_modulus_check.feature +25 -0
- data/lib/uk_account_validator.rb +41 -0
- data/lib/uk_account_validator/modulus_weight.rb +35 -0
- data/lib/uk_account_validator/modulus_weights_table.rb +31 -0
- data/lib/uk_account_validator/validator.rb +60 -0
- data/lib/uk_account_validator/validators/base_validator.rb +154 -0
- data/lib/uk_account_validator/validators/double_alternate.rb +38 -0
- data/lib/uk_account_validator/validators/modulus10.rb +9 -0
- data/lib/uk_account_validator/validators/modulus11.rb +9 -0
- data/lib/uk_account_validator/validators/standard_modulus.rb +33 -0
- data/lib/uk_account_validator/version.rb +3 -0
- data/uk_account_validator.gemspec +22 -0
- metadata +84 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
Feature: Exceptions
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given I create a new checker
|
5
|
+
|
6
|
+
Scenario Outline: Valid Codes
|
7
|
+
Given I have a sort code <sortcode>
|
8
|
+
And I have an account number <accountnumber>
|
9
|
+
|
10
|
+
Then the combination is valid
|
11
|
+
|
12
|
+
Examples:
|
13
|
+
| test | description | sortcode | accountnumber |
|
14
|
+
| 4 | Exception 10 & 11 where first check passes and second check fails. | 871427 | 46238510 |
|
15
|
+
| 5 | Exception 10 & 11 where first check fails and second check passes. | 872427 | 46238510 |
|
16
|
+
| 6 | Exception 10 where in the account number ab=09 and the g=9. The first check passes and second check fails. | 871427 | 09123496 |
|
17
|
+
| 7 | Exception 10 where in the account number ab=99 and the g=9. The first check passes and the second check fails. | 871427 | 99123496 |
|
18
|
+
| 8 | Exception 3, and the sorting code is the start of a range. As c=6 the second check should be ignored. | 820000 | 73688637 |
|
19
|
+
| 9 | Exception 3, and the sorting code is the end of a range. As c=9 the second check should be ignored. | 827999 | 73988638 |
|
20
|
+
| 10 | Exception 3. As c!=6 or 9 perform both checks pass. | 827101 | 28748352 |
|
21
|
+
| 11 | Exception 4 where the remainder is equal to the checkdigit. | 134020 | 63849203 |
|
22
|
+
| 12 | Exception 1 - ensures that 27 has been added to the accumulated total and passes double alternate modulus check. | 118765 | 64371389 |
|
23
|
+
| 13 | Exception 6 where the account fails standard check but is a foreign currency account. | 200915 | 41011166 |
|
24
|
+
| 14 | Exception 5 where the check passes. | 938611 | 07806039 |
|
25
|
+
| 15 | Exception 5 where the check passes with substitution. | 938600 | 42368003 |
|
26
|
+
| 16 | Exception 5 where both checks produce a remainder of 0 and pass. | 938063 | 55065200 |
|
27
|
+
| 17 | Exception 7 where passes but would fail the standard check. | 772798 | 99345694 |
|
28
|
+
| 18 | Exception 8 where the check passes. | 086090 | 06774744 |
|
29
|
+
| 19 | Exception 2 & 9 where the first check passes. | 309070 | 02355688 |
|
30
|
+
| 20 | Exception 2 & 9 where the first check fails and second check passes with substitution. | 309070 | 12345668 |
|
31
|
+
| 21 | Exception 2 & 9 where a!=0 and g!=9 and passes. | 309070 | 12345677 |
|
32
|
+
| 22 | Exception 2 & 9 where a!=0 and g=9 and passes. | 309070 | 99345694 |
|
33
|
+
| 31 | Exception 12/13 where passes modulus 11 check | 074456 | 12345112 |
|
34
|
+
| 32 | Exception 12/13 where passes the modulus 11 check | 070116 | 34012583 |
|
35
|
+
| 33 | Exception 12/13 where fails the modulus 11 check, but passes the modulus 10 check. | 074456 | 11104102 |
|
36
|
+
| 34 | Exception 14 where the first check fails and the second check passes. | 180002 | 00000190 |
|
37
|
+
|
38
|
+
Scenario Outline: Invalid Codes
|
39
|
+
Given I have a sort code <sortcode>
|
40
|
+
And I have an account number <accountnumber>
|
41
|
+
|
42
|
+
Then the combination is invalid
|
43
|
+
|
44
|
+
Examples:
|
45
|
+
| test | description | sortcode | accountnumber |
|
46
|
+
| 23 | Exception 5 where the first checkdigit is correct and the second incorrect. | 938063 | 15764273 |
|
47
|
+
| 24 | Exception 5 where the first checkdigit is incorrect and the second correct. | 938063 | 15764264 |
|
48
|
+
| 25 | Exception 5 where the first checkdigit is incorrect with a remainder of 1. | 938063 | 15763217 |
|
49
|
+
| 26 | Exception 1 where it fails double alternate check. | 118765 | 64371388 |
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Feature: Modulus 10 Checking
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given I create a new checker
|
5
|
+
|
6
|
+
Scenario: 1) Pass modulus 10 check
|
7
|
+
Given I have a sort code 089999
|
8
|
+
And I have an account number 66374958
|
9
|
+
|
10
|
+
Then the modulus is MOD10
|
11
|
+
And the combination is valid
|
12
|
+
|
13
|
+
Scenario: 29) Fail modulus 10 check
|
14
|
+
Given I have a sort code 089999
|
15
|
+
And I have an account number 66374959
|
16
|
+
|
17
|
+
Then the modulus is MOD10
|
18
|
+
And the combination is invalid
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Feature: Modulus 11 Checking
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given I create a new checker
|
5
|
+
|
6
|
+
Scenario: 2) Pass modulus 11 check
|
7
|
+
Given I have a sort code 107999
|
8
|
+
And I have an account number 88837491
|
9
|
+
|
10
|
+
Then the modulus is MOD11
|
11
|
+
And the combination is valid
|
12
|
+
|
13
|
+
Scenario: 30) Fail modulus 11 check
|
14
|
+
Given I have a sort code 107999
|
15
|
+
And I have an account number 88837493
|
@@ -0,0 +1,26 @@
|
|
1
|
+
Feature: Modulus Weight
|
2
|
+
|
3
|
+
Scenario: Reading Weights
|
4
|
+
Given I have the following weight data:
|
5
|
+
"""
|
6
|
+
070116 070116 MOD11 0 0 7 6 5 8 9 4 5 6 7 8 9 -1 12
|
7
|
+
"""
|
8
|
+
|
9
|
+
Then the weight's sort_code_start is 070116
|
10
|
+
And the weight's sort_code_end is 070116
|
11
|
+
And the weight's modulus is MOD11
|
12
|
+
And the weight's u is 0
|
13
|
+
And the weight's v is 0
|
14
|
+
And the weight's w is 7
|
15
|
+
And the weight's x is 6
|
16
|
+
And the weight's y is 5
|
17
|
+
And the weight's z is 8
|
18
|
+
And the weight's a is 9
|
19
|
+
And the weight's b is 4
|
20
|
+
And the weight's c is 5
|
21
|
+
And the weight's d is 6
|
22
|
+
And the weight's e is 7
|
23
|
+
And the weight's f is 8
|
24
|
+
And the weight's g is 9
|
25
|
+
And the weight's h is -1
|
26
|
+
And the weight's exception is 12
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Feature: Modulus Weight Table
|
2
|
+
|
3
|
+
Scenario: Finding appropriate modulus weight
|
4
|
+
Given I have a modulus weight table loaded from data/valacdos.txt
|
5
|
+
|
6
|
+
Then the modulus for sort code 010004 is MOD11
|
7
|
+
And the modulus for sort code 010005 is MOD11
|
8
|
+
And the modulus for sort code 016714 is MOD11
|
9
|
+
And the modulus for sort code 016715 is MOD11
|
10
|
+
|
11
|
+
Scenario: Sort code doesn't exist
|
12
|
+
Given I have a modulus weight table loaded from data/valacdos.txt
|
13
|
+
|
14
|
+
Then the modulus for sort code 020000 cannot be found
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Given(/^I create a new checker$/) do
|
2
|
+
@checker = UkAccountValidator::Validator.new
|
3
|
+
end
|
4
|
+
|
5
|
+
Given(/^I have a sort code (\d+)$/) do |sort_code|
|
6
|
+
@checker.sort_code = sort_code
|
7
|
+
end
|
8
|
+
|
9
|
+
Given(/^I have an account number (\d+)$/) do |acc_number|
|
10
|
+
@checker.account_number = acc_number
|
11
|
+
end
|
12
|
+
|
13
|
+
Then(/^the modulus is (\S+)$/) do |modulus|
|
14
|
+
expect(@checker.modulus_weights.first.modulus).to eq modulus
|
15
|
+
end
|
16
|
+
|
17
|
+
Then(/^the combination is valid$/) do
|
18
|
+
expect(@checker.valid?).to be true
|
19
|
+
end
|
20
|
+
|
21
|
+
Then(/^the combination is invalid$/) do
|
22
|
+
expect(@checker.valid?).to be false
|
23
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Given(/^I have a modulus weight table loaded from (.+?)$/) do |file_path|
|
2
|
+
@table = UkAccountValidator::ModulusWeightsTable.new(
|
3
|
+
File.join(File.dirname(__FILE__), '../..', file_path)
|
4
|
+
)
|
5
|
+
end
|
6
|
+
|
7
|
+
Then(/^the modulus for sort code (\d+) is (\S+)$/) do |sort_code, mod|
|
8
|
+
expect(@table.find(sort_code).first.modulus).to eq mod
|
9
|
+
end
|
10
|
+
|
11
|
+
Then(/^the modulus for sort code (\d+) cannot be found$/) do |sort_code|
|
12
|
+
expect(@table.find(sort_code)).to match_array([])
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Feature: Two Modulus Checks
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given I create a new checker
|
5
|
+
|
6
|
+
Scenario Outline: Valid Codes
|
7
|
+
Given I have a sort code <sortcode>
|
8
|
+
And I have an account number <accountnumber>
|
9
|
+
|
10
|
+
Then the combination is valid
|
11
|
+
|
12
|
+
Examples:
|
13
|
+
| test | description | sortcode | accountnumber |
|
14
|
+
| 3 | Pass modulus 11 and double alternate checks. | 202959 | 63748472 |
|
15
|
+
|
16
|
+
Scenario Outline: Invalid Codes
|
17
|
+
Given I have a sort code <sortcode>
|
18
|
+
And I have an account number <accountnumber>
|
19
|
+
|
20
|
+
Then the combination is invalid
|
21
|
+
|
22
|
+
Examples:
|
23
|
+
| test | description | sortcode | accountnumber |
|
24
|
+
| 27 | Pass modulus 11 check and fail double alternate check. | 203099 | 66831036 |
|
25
|
+
| 28 | Fail modulus 11 check and pass double alternate check. | 203099 | 58716970 |
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'uk_account_validator/validator.rb'
|
2
|
+
require 'uk_account_validator/modulus_weight.rb'
|
3
|
+
require 'uk_account_validator/modulus_weights_table.rb'
|
4
|
+
|
5
|
+
require 'uk_account_validator/validators/base_validator.rb'
|
6
|
+
require 'uk_account_validator/validators/standard_modulus.rb'
|
7
|
+
require 'uk_account_validator/validators/modulus10.rb'
|
8
|
+
require 'uk_account_validator/validators/modulus11.rb'
|
9
|
+
require 'uk_account_validator/validators/double_alternate.rb'
|
10
|
+
|
11
|
+
module UkAccountValidator
|
12
|
+
def self.modulus_weights_table
|
13
|
+
@modulus_weights_table ||= read_modulus_weights_table
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.sort_code_substitution
|
17
|
+
@sort_code_substitution ||= read_sort_code_substitution
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def self.modulus_weights_table_file
|
23
|
+
File.join(File.dirname(__FILE__), '../data/valacdos.txt')
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.read_modulus_weights_table
|
27
|
+
ModulusWeightsTable.new(modulus_weights_table_file)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.sort_code_substitution_file
|
31
|
+
File.join(File.dirname(__FILE__), '../data/scsubtab.txt')
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.read_sort_code_substitution
|
35
|
+
@substitutions ||= Hash[
|
36
|
+
File.readlines(UkAccountValidator.sort_code_substitution_file).map do |line|
|
37
|
+
line.split(' ')
|
38
|
+
end
|
39
|
+
]
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module UkAccountValidator
|
2
|
+
class ModulusWeight
|
3
|
+
attr_accessor :sort_code_start, :sort_code_end, :modulus, :u, :v, :w, :x,
|
4
|
+
:y, :z, :a, :b, :c, :d, :e, :f, :g, :h, :exception
|
5
|
+
|
6
|
+
# the size of each column
|
7
|
+
COLUMN_SIZES = [6, 7, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3]
|
8
|
+
|
9
|
+
# @param definition_line The line from valacdos.txt that defines this weight.
|
10
|
+
def self.from_line(definition_line)
|
11
|
+
# See https://www.ruby-forum.com/topic/184294#805359
|
12
|
+
data = definition_line.unpack("A#{COLUMN_SIZES.join('A')}")
|
13
|
+
|
14
|
+
data.map! { |d| d.strip }
|
15
|
+
|
16
|
+
@sort_code_start, @sort_code_end, @modulus, @u, @v, @w, @x,
|
17
|
+
@y, @z, @a, @b, @c, @d, @e, @f, @g, @h, @exception = data
|
18
|
+
|
19
|
+
ModulusWeight.new(*data)
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(sort_code_start, sort_code_end, modulus, u, v, w, x, y, z,
|
23
|
+
a, b, c, d, e, f, g, h, exception)
|
24
|
+
|
25
|
+
@sort_code_start = sort_code_start
|
26
|
+
@sort_code_end = sort_code_end
|
27
|
+
@modulus = modulus
|
28
|
+
@exception = exception
|
29
|
+
|
30
|
+
@u, @v, @w, @x, @y, @z, @a, @b, @c, @d, @e, @f, @g, @h =
|
31
|
+
[u.to_i, v.to_i, w.to_i, x.to_i, y.to_i, z.to_i, a.to_i, b.to_i, c.to_i,
|
32
|
+
d.to_i, e.to_i, f.to_i, g.to_i, h.to_i]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module UkAccountValidator
|
2
|
+
class ModulusWeightsTable
|
3
|
+
|
4
|
+
def initialize(path)
|
5
|
+
@weights = []
|
6
|
+
|
7
|
+
File.readlines(path).each do |line|
|
8
|
+
@weights << ModulusWeight.from_line(line)
|
9
|
+
end
|
10
|
+
|
11
|
+
@weights.sort! { |weight| weight.sort_code_start.to_i }
|
12
|
+
end
|
13
|
+
|
14
|
+
def find(sort_code, found_weights = [], exclude = [])
|
15
|
+
sort_code = sort_code.to_i
|
16
|
+
|
17
|
+
weight = @weights.bsearch do |w|
|
18
|
+
w.sort_code_start.to_i <= sort_code && !exclude.include?(w)
|
19
|
+
end
|
20
|
+
|
21
|
+
return found_weights if weight.nil?
|
22
|
+
return found_weights unless
|
23
|
+
weight.sort_code_start.to_i <= sort_code &&
|
24
|
+
sort_code <= weight.sort_code_end.to_i
|
25
|
+
|
26
|
+
found_weights << weight
|
27
|
+
|
28
|
+
find(sort_code, found_weights, exclude + [weight])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module UkAccountValidator
|
2
|
+
class Validator
|
3
|
+
attr_accessor :account_number, :sort_code
|
4
|
+
|
5
|
+
def initialize(account_number = nil, sort_code = nil)
|
6
|
+
@account_number = account_number
|
7
|
+
@sort_code = sort_code
|
8
|
+
end
|
9
|
+
|
10
|
+
def modulus_weights
|
11
|
+
@modulus_weights ||= UkAccountValidator.modulus_weights_table.find(sort_code)
|
12
|
+
end
|
13
|
+
|
14
|
+
def validator(modulus)
|
15
|
+
case modulus
|
16
|
+
when 'MOD10'
|
17
|
+
Validators::Modulus10
|
18
|
+
when 'MOD11'
|
19
|
+
Validators::Modulus11
|
20
|
+
when 'DBLAL'
|
21
|
+
Validators::DoubleAlternate
|
22
|
+
else
|
23
|
+
fail NotImplementedError
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid?
|
28
|
+
exceptions = modulus_weights.map(&:exception)
|
29
|
+
|
30
|
+
results = modulus_weights.each_with_index.map do |modulus_weight, i|
|
31
|
+
if i == 1 && exceptions.include?('2') && exceptions.include?('9')
|
32
|
+
next Validator.new(account_number, '309634').valid?
|
33
|
+
end
|
34
|
+
|
35
|
+
validator(modulus_weight.modulus).new(account_number, sort_code, modulus_weight, exceptions).valid?
|
36
|
+
end
|
37
|
+
|
38
|
+
return results.any? if exceptions.include?('2') && exceptions.include?('9')
|
39
|
+
return results.any? if exceptions.include?('10') && exceptions.include?('11')
|
40
|
+
return results.any? if exceptions.include?('12') && exceptions.include?('13')
|
41
|
+
return apply_exception_14 if !results.any? && exceptions.include?('14')
|
42
|
+
|
43
|
+
results.all?
|
44
|
+
end
|
45
|
+
|
46
|
+
# If the 8th digit of the account number (reading from left to right) is
|
47
|
+
# not 0, 1 or 9 then the account number fails the second check and is not a
|
48
|
+
# valid Coutts account number.
|
49
|
+
# If the 8th digit is 0, 1 or 9, then remove the digit from the account
|
50
|
+
# number and insert a 0 as the 1st digit for check purposes only
|
51
|
+
def apply_exception_14
|
52
|
+
return false unless %w(0 1 9).include?(account_number[7])
|
53
|
+
|
54
|
+
account_number.slice!(7)
|
55
|
+
exception_account_number = '0' + account_number
|
56
|
+
|
57
|
+
return Validator.new(exception_account_number, sort_code).valid?
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
module UkAccountValidator
|
2
|
+
module Validators
|
3
|
+
class BaseValidator
|
4
|
+
NUMBER_INDEX = {
|
5
|
+
u: 0,
|
6
|
+
v: 1,
|
7
|
+
w: 2,
|
8
|
+
x: 3,
|
9
|
+
y: 4,
|
10
|
+
z: 5,
|
11
|
+
a: 6,
|
12
|
+
b: 7,
|
13
|
+
c: 8,
|
14
|
+
d: 9,
|
15
|
+
e: 10,
|
16
|
+
f: 11,
|
17
|
+
g: 12,
|
18
|
+
h: 13
|
19
|
+
}
|
20
|
+
|
21
|
+
def initialize(account_number, sort_code, modulus_weight, exceptions)
|
22
|
+
@account_number = account_number
|
23
|
+
@sort_code = sort_code
|
24
|
+
@modulus_weight = modulus_weight
|
25
|
+
@exceptions = exceptions
|
26
|
+
|
27
|
+
@sort_code = apply_exception_5_substitutions(sort_code) if @modulus_weight.exception == '5'
|
28
|
+
end
|
29
|
+
|
30
|
+
def applying_exceptions(test_digits)
|
31
|
+
apply_exception_2_9(test_digits) if @exceptions.include?('2') && @exceptions.include?('9')
|
32
|
+
apply_exception_3(test_digits) if @modulus_weight.exception == '3'
|
33
|
+
apply_exception_6(test_digits) if @modulus_weight.exception == '6'
|
34
|
+
apply_exception_7(test_digits) if @modulus_weight.exception == '7'
|
35
|
+
apply_exception_8(test_digits) if @modulus_weight.exception == '8'
|
36
|
+
apply_exception_10(test_digits) if @modulus_weight.exception == '10'
|
37
|
+
|
38
|
+
total = yield
|
39
|
+
|
40
|
+
total += 27 if @modulus_weight.exception == '1'
|
41
|
+
|
42
|
+
total
|
43
|
+
end
|
44
|
+
|
45
|
+
def zero_all
|
46
|
+
@modulus_weight = ModulusWeight.new(
|
47
|
+
@modulus_weight.sort_code_start,
|
48
|
+
@modulus_weight.sort_code_end,
|
49
|
+
@modulus_weight.modulus,
|
50
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
51
|
+
@modulus_weight.exception
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
def zero_u_b
|
56
|
+
@modulus_weight = ModulusWeight.new(
|
57
|
+
@modulus_weight.sort_code_start,
|
58
|
+
@modulus_weight.sort_code_end,
|
59
|
+
@modulus_weight.modulus,
|
60
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
61
|
+
@modulus_weight.c, @modulus_weight.d, @modulus_weight.e,
|
62
|
+
@modulus_weight.f, @modulus_weight.g, @modulus_weight.h,
|
63
|
+
@modulus_weight.exception
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
def apply_exception_2_9(test_digits)
|
68
|
+
return if test_digits[NUMBER_INDEX[:a]] == 0
|
69
|
+
|
70
|
+
if test_digits[NUMBER_INDEX[:g]] != 9
|
71
|
+
@modulus_weight = ModulusWeight.new(
|
72
|
+
@modulus_weight.sort_code_start,
|
73
|
+
@modulus_weight.sort_code_end,
|
74
|
+
@modulus_weight.modulus,
|
75
|
+
0, 0, 1, 2, 5, 3, 6, 4, 8, 7, 10, 9, 3, 1,
|
76
|
+
@modulus_weight.exception
|
77
|
+
)
|
78
|
+
else
|
79
|
+
@modulus_weight = ModulusWeight.new(
|
80
|
+
@modulus_weight.sort_code_start,
|
81
|
+
@modulus_weight.sort_code_end,
|
82
|
+
@modulus_weight.modulus,
|
83
|
+
0, 0, 0, 0, 0, 0, 0, 0, 8, 7, 10, 9, 3, 1,
|
84
|
+
@modulus_weight.exception
|
85
|
+
)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def apply_exception_3(test_digits)
|
90
|
+
c = test_digits[NUMBER_INDEX[:c]]
|
91
|
+
zero_all if c == 6 || c == 9
|
92
|
+
end
|
93
|
+
|
94
|
+
def apply_exception_4(total, test_digits)
|
95
|
+
check_sum = [test_digits[NUMBER_INDEX[:g]], test_digits[NUMBER_INDEX[:h]]].join
|
96
|
+
check_sum = check_sum.to_i
|
97
|
+
|
98
|
+
total % modulus == check_sum
|
99
|
+
end
|
100
|
+
|
101
|
+
def apply_exception_5_substitutions(sort_code)
|
102
|
+
substitutions = UkAccountValidator.read_sort_code_substitution
|
103
|
+
|
104
|
+
if substitutions.keys.include?(sort_code)
|
105
|
+
sort_code = substitutions[sort_code]
|
106
|
+
end
|
107
|
+
|
108
|
+
return sort_code
|
109
|
+
end
|
110
|
+
|
111
|
+
def apply_exception_5(total, test_digits, check_digit)
|
112
|
+
check_sum = total % modulus
|
113
|
+
expected_sum = test_digits[NUMBER_INDEX[check_digit]].to_i
|
114
|
+
|
115
|
+
return false if check_sum == 1 && check_digit == :g
|
116
|
+
return true if check_sum == 0 && expected_sum == 0
|
117
|
+
|
118
|
+
return (modulus - check_sum) == expected_sum
|
119
|
+
end
|
120
|
+
|
121
|
+
# If a = 4, 5, 6, 7 or 8, and g and h are the same
|
122
|
+
def apply_exception_6(test_digits)
|
123
|
+
a = test_digits[NUMBER_INDEX[:a]]
|
124
|
+
g = test_digits[NUMBER_INDEX[:g]]
|
125
|
+
h = test_digits[NUMBER_INDEX[:h]]
|
126
|
+
|
127
|
+
zero_all if (a == 4 || a == 5 || a == 6 || a == 7 || a == 8) && g == h
|
128
|
+
end
|
129
|
+
|
130
|
+
def apply_exception_7(test_digits)
|
131
|
+
return unless test_digits[NUMBER_INDEX[:g]] == 9
|
132
|
+
|
133
|
+
zero_u_b
|
134
|
+
end
|
135
|
+
|
136
|
+
def apply_exception_8(test_digits)
|
137
|
+
test_string = '090126' + @account_number
|
138
|
+
|
139
|
+
test_digits.replace(test_string.split(//).map(&:to_i))
|
140
|
+
end
|
141
|
+
|
142
|
+
def apply_exception_10(test_digits)
|
143
|
+
# if ab = 09 or 99 and g=9, zeroise weighting positions u-b.
|
144
|
+
a = test_digits[NUMBER_INDEX[:a]]
|
145
|
+
b = test_digits[NUMBER_INDEX[:b]]
|
146
|
+
|
147
|
+
return unless (a == 0 && b == 9) ||
|
148
|
+
(a == 9 && b == 9 && test_digits[NUMBER_INDEX[:g]] == 9)
|
149
|
+
|
150
|
+
zero_u_b
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|