uk_account_validator 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.
- 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
|