uk_account_validator_auctionet 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rubocop.yml +11 -0
  4. data/.travis.yml +14 -0
  5. data/Gemfile +14 -0
  6. data/LICENSE.txt +23 -0
  7. data/README.md +51 -0
  8. data/Rakefile +11 -0
  9. data/data/scsubtab.txt +21 -0
  10. data/data/valacdos.txt +1074 -0
  11. data/features/allow_hyphens_in_sort_codes.feature +9 -0
  12. data/features/exceptions.feature +49 -0
  13. data/features/invalid_formats.feature +33 -0
  14. data/features/modulus10.feature +18 -0
  15. data/features/modulus11.feature +18 -0
  16. data/features/modulus_weight.feature +26 -0
  17. data/features/modulus_weights_table.feature +14 -0
  18. data/features/step_definitions/basics.rb +23 -0
  19. data/features/step_definitions/modulus_weight.rb +7 -0
  20. data/features/step_definitions/modulus_weights_table.rb +13 -0
  21. data/features/support/env.rb +2 -0
  22. data/features/two_modulus_check.feature +25 -0
  23. data/lib/uk_account_validator.rb +57 -0
  24. data/lib/uk_account_validator/backports/array_bsearch_index.rb +33 -0
  25. data/lib/uk_account_validator/exceptions/base_exception.rb +65 -0
  26. data/lib/uk_account_validator/exceptions/exception_1.rb +10 -0
  27. data/lib/uk_account_validator/exceptions/exception_10.rb +18 -0
  28. data/lib/uk_account_validator/exceptions/exception_12.rb +9 -0
  29. data/lib/uk_account_validator/exceptions/exception_14.rb +30 -0
  30. data/lib/uk_account_validator/exceptions/exception_2_9.rb +68 -0
  31. data/lib/uk_account_validator/exceptions/exception_3.rb +10 -0
  32. data/lib/uk_account_validator/exceptions/exception_4.rb +16 -0
  33. data/lib/uk_account_validator/exceptions/exception_5.rb +48 -0
  34. data/lib/uk_account_validator/exceptions/exception_6.rb +16 -0
  35. data/lib/uk_account_validator/exceptions/exception_7.rb +9 -0
  36. data/lib/uk_account_validator/exceptions/exception_8.rb +7 -0
  37. data/lib/uk_account_validator/modulus_weight.rb +35 -0
  38. data/lib/uk_account_validator/modulus_weights_table.rb +35 -0
  39. data/lib/uk_account_validator/number_indices.rb +18 -0
  40. data/lib/uk_account_validator/validator.rb +92 -0
  41. data/lib/uk_account_validator/validators/base_validator.rb +28 -0
  42. data/lib/uk_account_validator/validators/double_alternate.rb +35 -0
  43. data/lib/uk_account_validator/validators/modulus10.rb +9 -0
  44. data/lib/uk_account_validator/validators/modulus11.rb +9 -0
  45. data/lib/uk_account_validator/validators/standard_modulus.rb +30 -0
  46. data/lib/uk_account_validator/version.rb +3 -0
  47. data/uk_account_validator.gemspec +22 -0
  48. metadata +104 -0
@@ -0,0 +1,9 @@
1
+ Feature: Allow hyphens in sort codes
2
+ Background:
3
+ Given I create a new checker
4
+
5
+ Scenario: A user supplies a valid sort code separated by hyphens
6
+ Given I have a sort code 08-99-99
7
+ And I have an account number 66374958
8
+
9
+ Then the combination is valid
@@ -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,33 @@
1
+ Feature: Account number and sort code must be in recognised format
2
+ Background:
3
+ Given I create a new checker
4
+
5
+ Scenario: Account number contains letters
6
+ Given I have a sort code 089999
7
+ And I have an account number abcdefgh
8
+
9
+ Then the combination is invalid
10
+
11
+ Scenario: Account number must be at least 6 digits
12
+ Given I have a sort code 089999
13
+ And I have an account number 66374
14
+
15
+ Then the combination is invalid
16
+
17
+ Scenario: Account number may not be more than 10 digits
18
+ Given I have a sort code 089999
19
+ And I have an account number 66374958663
20
+
21
+ Then the combination is invalid
22
+
23
+ Scenario: The sort code may not be less than 6 digits
24
+ Given I have a sort code 08999
25
+ And I have an account number 66374958
26
+
27
+ Then the combination is invalid
28
+
29
+ Scenario: The sort code may not be more than 6 digits
30
+ Given I have a sort code 0899999
31
+ And I have an account number 66374958
32
+
33
+ Then the combination is invalid
@@ -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,18 @@
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
16
+
17
+ Then the modulus is MOD11
18
+ And the combination is invalid
@@ -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 (\S+)$/) do |sort_code|
6
+ @checker.sort_code = sort_code
7
+ end
8
+
9
+ Given(/^I have an account number (\S+)$/) 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,7 @@
1
+ Given(/^I have the following weight data:$/) do |weight_data|
2
+ @weight = UkAccountValidator::ModulusWeight.from_line(weight_data)
3
+ end
4
+
5
+ Then(/^the weight's (\S+) is (\S+)$/) do |arg, value|
6
+ expect(@weight.send(arg).to_s).to eq value
7
+ 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,2 @@
1
+ $LOAD_PATH << File.expand_path('../../lib', File.dirname(__FILE__))
2
+ require 'uk_account_validator'
@@ -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,57 @@
1
+ require 'uk_account_validator/backports/array_bsearch_index'
2
+
3
+ require 'uk_account_validator/number_indices.rb'
4
+ require 'uk_account_validator/validator.rb'
5
+ require 'uk_account_validator/modulus_weight.rb'
6
+ require 'uk_account_validator/modulus_weights_table.rb'
7
+
8
+ require 'uk_account_validator/validators/base_validator.rb'
9
+ require 'uk_account_validator/validators/standard_modulus.rb'
10
+ require 'uk_account_validator/validators/modulus10.rb'
11
+ require 'uk_account_validator/validators/modulus11.rb'
12
+ require 'uk_account_validator/validators/double_alternate.rb'
13
+
14
+ require 'uk_account_validator/exceptions/base_exception.rb'
15
+ require 'uk_account_validator/exceptions/exception_1.rb'
16
+ require 'uk_account_validator/exceptions/exception_2_9.rb'
17
+ require 'uk_account_validator/exceptions/exception_3.rb'
18
+ require 'uk_account_validator/exceptions/exception_4.rb'
19
+ require 'uk_account_validator/exceptions/exception_5.rb'
20
+ require 'uk_account_validator/exceptions/exception_6.rb'
21
+ require 'uk_account_validator/exceptions/exception_7.rb'
22
+ require 'uk_account_validator/exceptions/exception_8.rb'
23
+ require 'uk_account_validator/exceptions/exception_10.rb'
24
+ require 'uk_account_validator/exceptions/exception_12.rb'
25
+ require 'uk_account_validator/exceptions/exception_14.rb'
26
+
27
+ module UkAccountValidator
28
+ def self.modulus_weights_table
29
+ @modulus_weights_table ||= read_modulus_weights_table
30
+ end
31
+
32
+ def self.sort_code_substitution
33
+ @sort_code_substitution ||= read_sort_code_substitution
34
+ end
35
+
36
+ private
37
+
38
+ def self.modulus_weights_table_file
39
+ File.join(File.dirname(__FILE__), '../data/valacdos.txt')
40
+ end
41
+
42
+ def self.read_modulus_weights_table
43
+ ModulusWeightsTable.new(modulus_weights_table_file)
44
+ end
45
+
46
+ def self.sort_code_substitution_file
47
+ File.join(File.dirname(__FILE__), '../data/scsubtab.txt')
48
+ end
49
+
50
+ def self.read_sort_code_substitution
51
+ @substitutions ||= Hash[
52
+ File.readlines(UkAccountValidator.sort_code_substitution_file).map do |line|
53
+ line.split(' ')
54
+ end
55
+ ]
56
+ end
57
+ end
@@ -0,0 +1,33 @@
1
+ # Copied from backports gem
2
+ unless Array.method_defined? :bsearch_index
3
+ class Array
4
+ def bsearch_index
5
+ return to_enum(__method__) unless block_given?
6
+ from = 0
7
+ to = size - 1
8
+ satisfied = nil
9
+ while from <= to do
10
+ midpoint = (from + to).div(2)
11
+ result = yield(self[midpoint])
12
+ case result
13
+ when Numeric
14
+ return midpoint if result == 0
15
+ result = result < 0
16
+ when true
17
+ satisfied = midpoint
18
+ when nil, false
19
+ # nothing to do
20
+ else
21
+ raise TypeError, "wrong argument type #{result.class} (must be numeric, true, false or nil)"
22
+ end
23
+
24
+ if result
25
+ to = midpoint - 1
26
+ else
27
+ from = midpoint + 1
28
+ end
29
+ end
30
+ satisfied
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,65 @@
1
+ class BaseException
2
+ include NumberIndices
3
+
4
+ attr_reader :modulus_weight, :account_number, :sort_code, :check_number
5
+
6
+ def initialize(modulus_weight, account_number, sort_code, check_number)
7
+ @modulus_weight = modulus_weight
8
+ @account_number = account_number
9
+ @sort_code = sort_code
10
+ @check_number = check_number
11
+ end
12
+
13
+ def self.allow_any?
14
+ false
15
+ end
16
+
17
+ def override_test?
18
+ false
19
+ end
20
+
21
+ # Returns the new modulus weight after applying the exception.
22
+ def replace_weight(_test_digits)
23
+ return modulus_weight
24
+ end
25
+
26
+ # Returns the new total after any adjustments
27
+ def after_calculate_total(total, _test_digits)
28
+ return total
29
+ end
30
+
31
+ def apply_account_number_substitutions
32
+ return account_number
33
+ end
34
+
35
+ # Returns the new sort code after substitutions
36
+ def apply_sort_code_substitutions
37
+ return sort_code
38
+ end
39
+
40
+ # Useful functions
41
+
42
+ # Zero all weights
43
+ def zero_all
44
+ UkAccountValidator::ModulusWeight.new(
45
+ modulus_weight.sort_code_start,
46
+ modulus_weight.sort_code_end,
47
+ modulus_weight.modulus,
48
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49
+ modulus_weight.exception
50
+ )
51
+ end
52
+
53
+ # Zero weights for u to b
54
+ def zero_u_b
55
+ UkAccountValidator::ModulusWeight.new(
56
+ modulus_weight.sort_code_start,
57
+ modulus_weight.sort_code_end,
58
+ modulus_weight.modulus,
59
+ 0, 0, 0, 0, 0, 0, 0, 0,
60
+ modulus_weight.c, modulus_weight.d, modulus_weight.e,
61
+ modulus_weight.f, modulus_weight.g, modulus_weight.h,
62
+ modulus_weight.exception
63
+ )
64
+ end
65
+ end
@@ -0,0 +1,10 @@
1
+ # Perform the double alternate check except:
2
+ # Add 27 to the total (ie before you divide by 10)
3
+ # This effectively places a financial institution number (580149) before the
4
+ # sorting code and account number which is subject to the alternate doubling as
5
+ # well.
6
+ class Exception1 < BaseException
7
+ def after_calculate_total(total, _test_digits)
8
+ return total + 27
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+ # For the exception 10 check, if ab = 09 or ab = 99 and g = 9, zeroise weighting
2
+ # positions u-b.
3
+ class Exception10 < BaseException
4
+ def self.allow_any?
5
+ true
6
+ end
7
+
8
+ def replace_weight(test_digits)
9
+ # if ab = 09 or 99 and g=9, zeroise weighting positions u-b.
10
+ a = test_digits[NUMBER_INDEX[:a]]
11
+ b = test_digits[NUMBER_INDEX[:b]]
12
+
13
+ return zero_u_b if (a == 0 && b == 9) ||
14
+ (a == 9 && b == 9 && test_digits[NUMBER_INDEX[:g]] == 9)
15
+
16
+ return modulus_weight
17
+ end
18
+ end