tracking_number 1.0.3 → 1.0.7
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 +4 -4
- data/.github/workflows/ruby.yml +20 -0
- data/.travis.yml +3 -3
- data/Gemfile +1 -1
- data/README.md +5 -4
- data/lib/data/couriers/usps.json +3 -3
- data/lib/tracking_number/active_model_validator.rb +1 -1
- data/lib/tracking_number/base.rb +18 -6
- data/lib/tracking_number/checksum_validations.rb +65 -0
- data/lib/tracking_number/info.rb +8 -0
- data/lib/tracking_number/loader.rb +73 -0
- data/lib/tracking_number/version.rb +1 -1
- data/lib/tracking_number.rb +3 -62
- data/test/tracking_number_meta_test.rb +39 -40
- data/test/tracking_number_test.rb +15 -0
- data/tracking_number.gemspec +3 -2
- metadata +14 -9
- data/lib/checksum_validations.rb +0 -63
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f3a1ee8c8aa65591877507ca7c24ee28fc958309b2788ffb794aac3051aeb33
|
4
|
+
data.tar.gz: 354a02937aaad7e4bfad81ecb34f4fcf3879cf045a58995ab161410e034892cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c372d83366a97478d4e7e5ebc8b591d9e1271236b97d6a93dcb3f2e603241e8d2f270ff5bfae9c4b59b3898b665c711fa5c2661ae5df954a9cca3d9e23523519
|
7
|
+
data.tar.gz: f92fb5029565b16f24315769bd1dabef1987c16312ab8d6942df085cdebe635a320b8f4dbbe043dd6bfd52404b49c7c1b77b78dceec65924fe6253381951b93c
|
@@ -0,0 +1,20 @@
|
|
1
|
+
name: Ruby
|
2
|
+
|
3
|
+
on: [push]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
build:
|
7
|
+
|
8
|
+
runs-on: ubuntu-latest
|
9
|
+
|
10
|
+
steps:
|
11
|
+
- uses: actions/checkout@v1
|
12
|
+
- name: Set up Ruby 2.6
|
13
|
+
uses: actions/setup-ruby@v1
|
14
|
+
with:
|
15
|
+
ruby-version: 2.6.x
|
16
|
+
- name: Build and test with Rake
|
17
|
+
run: |
|
18
|
+
gem install bundler
|
19
|
+
bundle install --jobs 4 --retry 3
|
20
|
+
bundle exec rake
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -9,6 +9,10 @@ It detects tracking numbers from UPS, FedEx, DHL, USPS, OnTrac, Amazon Logistics
|
|
9
9
|
|
10
10
|
This gem does not do tracking. That is left up to you.
|
11
11
|
|
12
|
+
#### New in 1.0
|
13
|
+
|
14
|
+
Starting with the 1.0 release the specifications for detecting tracking numbers have been moved into a separate repository ([tracking_number_data](http://github.com/jkeen/tracking_number_data)) that this gem relies on. I did this so a) we can have a single place to document all tracking number types and it can be more of a crowdsourced effort, and b) so clients can be written in other languages easier.
|
15
|
+
|
12
16
|
## Usage
|
13
17
|
|
14
18
|
#### Checking an individual tracking number
|
@@ -119,9 +123,6 @@ class Shipment < ActiveRecord::Base
|
|
119
123
|
end
|
120
124
|
```
|
121
125
|
|
122
|
-
## Where the data comes from
|
123
|
-
Starting with the 1.0 release of this gem the data for tracking numbers has been extracted into a separate repository ([tracking_number_data](http://github.com/jkeen/tracking_number_data)) so non-ruby clients can benefit from the detection/documentation that used to be contained deep in the code of this gem. If you want to write a client in some other language, that's the stuff you want.
|
124
|
-
|
125
126
|
## Contributing to tracking_number
|
126
127
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
127
128
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
@@ -133,5 +134,5 @@ Starting with the 1.0 release of this gem the data for tracking numbers has been
|
|
133
134
|
|
134
135
|
## Copyright
|
135
136
|
|
136
|
-
Copyright (c) 2010-
|
137
|
+
Copyright (c) 2010-2021 Jeff Keen. See LICENSE.txt for
|
137
138
|
further details.
|
data/lib/data/couriers/usps.json
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
"courier_code": "usps",
|
4
4
|
"tracking_numbers": [
|
5
5
|
{
|
6
|
-
"tracking_url": "https://
|
6
|
+
"tracking_url": "https://tools.usps.com/go/TrackConfirmAction?tLabels=%s",
|
7
7
|
"name": "USPS 20",
|
8
8
|
"description": "20 digit USPS numbers",
|
9
9
|
"regex": [
|
@@ -76,7 +76,7 @@
|
|
76
76
|
"odds_multiplier": 1
|
77
77
|
}
|
78
78
|
},
|
79
|
-
"tracking_url": "https://
|
79
|
+
"tracking_url": "https://tools.usps.com/go/TrackConfirmAction?tLabels=%s",
|
80
80
|
"test_numbers": {
|
81
81
|
"valid": [
|
82
82
|
"4201002334249200190132607600833457",
|
@@ -115,7 +115,7 @@
|
|
115
115
|
}
|
116
116
|
}
|
117
117
|
},
|
118
|
-
"tracking_url": "https://
|
118
|
+
"tracking_url": "https://tools.usps.com/go/TrackConfirmAction?tLabels=%s",
|
119
119
|
"test_numbers": {
|
120
120
|
"valid": [
|
121
121
|
"420 22153 9101026837331000039521",
|
@@ -6,7 +6,7 @@ class TrackingNumberValidator < ActiveModel::EachValidator
|
|
6
6
|
elsif TrackingNumber.new(value).valid?
|
7
7
|
# looks good to me
|
8
8
|
else
|
9
|
-
record.errors
|
9
|
+
record.errors.add(attribute, options[:message] || 'is not a valid tracking number')
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
data/lib/tracking_number/base.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'checksum_validations'
|
2
|
-
|
3
1
|
module TrackingNumber
|
4
2
|
class Base
|
5
3
|
attr_accessor :tracking_number
|
@@ -95,7 +93,7 @@ module TrackingNumber
|
|
95
93
|
name = checksum_info[:name]
|
96
94
|
method_name = "validates_#{name}?"
|
97
95
|
|
98
|
-
ChecksumValidations.send(method_name, serial_number, check_digit, checksum_info)
|
96
|
+
TrackingNumber::ChecksumValidations.send(method_name, serial_number, check_digit, checksum_info)
|
99
97
|
end
|
100
98
|
|
101
99
|
def to_s
|
@@ -113,8 +111,7 @@ module TrackingNumber
|
|
113
111
|
:service_description => service_description,
|
114
112
|
:destination_zip => destination_zip,
|
115
113
|
:shipper_id => shipper_id,
|
116
|
-
:package_type => package_type
|
117
|
-
:package_description => package_description
|
114
|
+
:package_type => package_type
|
118
115
|
})
|
119
116
|
end
|
120
117
|
|
@@ -159,7 +156,7 @@ module TrackingNumber
|
|
159
156
|
end
|
160
157
|
|
161
158
|
def package_type
|
162
|
-
if matching_additional["
|
159
|
+
if matching_additional["Container Type"]
|
163
160
|
@package_type ||= Info.new(matching_additional["Container Type"]).name
|
164
161
|
end
|
165
162
|
end
|
@@ -172,6 +169,21 @@ module TrackingNumber
|
|
172
169
|
match_group("ShipperId")
|
173
170
|
end
|
174
171
|
|
172
|
+
def tracking_url
|
173
|
+
url = nil
|
174
|
+
if matching_additional["Courier"]
|
175
|
+
url = matching_additional["Courier"][:tracking_url]
|
176
|
+
else
|
177
|
+
if self.class.const_defined?(:TRACKING_URL)
|
178
|
+
url = self.class.const_get(:TRACKING_URL)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
if url
|
183
|
+
url.sub('%s', self.tracking_number)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
175
187
|
def matching_additional
|
176
188
|
additional = self.class.const_get(:ADDITIONAL) || []
|
177
189
|
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module TrackingNumber
|
2
|
+
module ChecksumValidations
|
3
|
+
class << self
|
4
|
+
def validates_s10?(sequence, check_digit, extras = {})
|
5
|
+
weighting = [8,6,4,2,3,5,9,7]
|
6
|
+
|
7
|
+
total = 0
|
8
|
+
sequence.chars.to_a.zip(weighting).each do |(a,b)|
|
9
|
+
total += a.to_i * b.to_i
|
10
|
+
end
|
11
|
+
|
12
|
+
remainder = total % 11
|
13
|
+
check = case remainder
|
14
|
+
when 1
|
15
|
+
0
|
16
|
+
when 0
|
17
|
+
5
|
18
|
+
else
|
19
|
+
11 - remainder
|
20
|
+
end
|
21
|
+
|
22
|
+
return check.to_i == check_digit.to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
def validates_sum_product_with_weightings_and_modulo?(sequence, check_digit, extras = {})
|
26
|
+
weighting = extras[:weightings] || []
|
27
|
+
|
28
|
+
total = 0
|
29
|
+
sequence.chars.to_a.zip(weighting).each do |(a,b)|
|
30
|
+
total += a.to_i * b
|
31
|
+
end
|
32
|
+
return (total % extras[:modulo1] % extras[:modulo2]) == check_digit.to_i
|
33
|
+
end
|
34
|
+
|
35
|
+
def validates_mod10?(sequence, check_digit, extras = {})
|
36
|
+
total = 0
|
37
|
+
sequence.chars.each_with_index do |c, i|
|
38
|
+
x = if c[/[0-9]/] # numeric
|
39
|
+
c.to_i
|
40
|
+
else
|
41
|
+
(c[0].ord - 3) % 10
|
42
|
+
end
|
43
|
+
|
44
|
+
if extras[:odds_multiplier] && i.odd?
|
45
|
+
x *= extras[:odds_multiplier].to_i
|
46
|
+
elsif extras[:evens_multiplier] && i.even?
|
47
|
+
x *= extras[:evens_multiplier].to_i
|
48
|
+
end
|
49
|
+
|
50
|
+
total += x
|
51
|
+
end
|
52
|
+
|
53
|
+
check = (total % 10)
|
54
|
+
check = (10 - check) unless (check.zero?)
|
55
|
+
|
56
|
+
return (check.to_i == check_digit.to_i)
|
57
|
+
end
|
58
|
+
|
59
|
+
def validates_mod7?(sequence, check_digit, extras = {})
|
60
|
+
# standard mod 7 check
|
61
|
+
return true if sequence.to_i % 7 == check_digit.to_i
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/tracking_number/info.rb
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
|
2
|
+
module TrackingNumber
|
3
|
+
module Loader
|
4
|
+
class << self
|
5
|
+
def load_tracking_number_data
|
6
|
+
tracking_number_types = []
|
7
|
+
|
8
|
+
Dir.glob(File.join(File.dirname(__FILE__), "../data/couriers/*.json")).each do |file|
|
9
|
+
courier_info = read_courier_info(file)
|
10
|
+
|
11
|
+
courier_info[:tracking_numbers].each do |tracking_info|
|
12
|
+
tracking_name = tracking_info[:name]
|
13
|
+
klass = create_class(klass, courier_info, tracking_info)
|
14
|
+
|
15
|
+
# Do some basic checks on the data file
|
16
|
+
throw 'missing test numbers' unless has_test_numbers?(tracking_info)
|
17
|
+
throw 'missing regex match groups' unless test_numbers_return_required_groups?(tracking_info, Regexp.new(klass::VERIFY_PATTERN))
|
18
|
+
|
19
|
+
const = register_class(klass, tracking_name)
|
20
|
+
tracking_number_types.push(const)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
TrackingNumber.const_set("TYPES", tracking_number_types)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def has_test_numbers?(tracking)
|
30
|
+
return tracking[:test_numbers] && tracking[:test_numbers][:valid]
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_numbers_return_required_groups?(tracking, regex)
|
34
|
+
test_number = tracking[:test_numbers][:valid][0]
|
35
|
+
matches = test_number.match(regex)
|
36
|
+
|
37
|
+
return matches["SerialNumber"]
|
38
|
+
end
|
39
|
+
|
40
|
+
def read_courier_info(file)
|
41
|
+
return JSON.parse(File.read(file)).deep_symbolize_keys!
|
42
|
+
end
|
43
|
+
|
44
|
+
def create_class(klass, courier_info, tracking_info)
|
45
|
+
klass = Class.new(TrackingNumber::Base)
|
46
|
+
klass.const_set("COURIER_CODE", courier_info[:courier_code])
|
47
|
+
info = courier_info.dup
|
48
|
+
info.delete(:tracking_numbers)
|
49
|
+
klass.const_set("COURIER_INFO", info)
|
50
|
+
|
51
|
+
pattern = tracking_info[:regex]
|
52
|
+
pattern = tracking_info[:regex].join if tracking_info[:regex].is_a?(Array)
|
53
|
+
|
54
|
+
verify_pattern = "^#{pattern}$"
|
55
|
+
search_pattern = "\\b#{pattern}\\b"
|
56
|
+
|
57
|
+
klass.const_set("SEARCH_PATTERN", Regexp.new(search_pattern))
|
58
|
+
klass.const_set("VERIFY_PATTERN", Regexp.new(verify_pattern))
|
59
|
+
|
60
|
+
klass.const_set("VALIDATION", tracking_info[:validation])
|
61
|
+
klass.const_set("ADDITIONAL", tracking_info[:additional])
|
62
|
+
klass.const_set("TRACKING_URL", tracking_info[:tracking_url])
|
63
|
+
|
64
|
+
return klass
|
65
|
+
end
|
66
|
+
|
67
|
+
def register_class(klass, tracking_name)
|
68
|
+
klass_name = tracking_name.gsub(/[^0-9A-Za-z]/, '')
|
69
|
+
return TrackingNumber.const_set(klass_name, klass)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/tracking_number.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# Identify if tracking numbers are valid, and which service they belong to
|
2
2
|
|
3
3
|
require 'json'
|
4
|
+
require 'tracking_number/checksum_validations'
|
5
|
+
require 'tracking_number/loader'
|
4
6
|
require 'tracking_number/base'
|
5
7
|
require 'tracking_number/info'
|
6
8
|
require 'tracking_number/unknown'
|
7
|
-
require 'checksum_validations'
|
8
9
|
require 'active_support/core_ext/string'
|
9
10
|
require 'active_support/core_ext/hash'
|
10
11
|
|
@@ -12,67 +13,7 @@ if defined?(ActiveModel::EachValidator)
|
|
12
13
|
require 'tracking_number/active_model_validator'
|
13
14
|
end
|
14
15
|
|
15
|
-
|
16
|
-
return tracking[:test_numbers] && tracking[:test_numbers][:valid]
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_numbers_return_required_groups?(tracking, regex)
|
20
|
-
test_number = tracking[:test_numbers][:valid][0]
|
21
|
-
matches = test_number.match(regex)
|
22
|
-
|
23
|
-
return matches["SerialNumber"]
|
24
|
-
end
|
25
|
-
|
26
|
-
def read_courier_info(file)
|
27
|
-
return JSON.parse(File.read(file)).deep_symbolize_keys!
|
28
|
-
end
|
29
|
-
|
30
|
-
def create_class(klass, courier_info, tracking_info)
|
31
|
-
klass = Class.new(TrackingNumber::Base)
|
32
|
-
klass.const_set("COURIER_CODE", courier_info[:courier_code])
|
33
|
-
info = courier_info.dup
|
34
|
-
info.delete(:tracking_numbers)
|
35
|
-
klass.const_set("COURIER_INFO", info)
|
36
|
-
|
37
|
-
pattern = tracking_info[:regex]
|
38
|
-
pattern = tracking_info[:regex].join if tracking_info[:regex].is_a?(Array)
|
39
|
-
|
40
|
-
verify_pattern = "^#{pattern}$"
|
41
|
-
search_pattern = "\\b#{pattern}\\b"
|
42
|
-
|
43
|
-
klass.const_set("SEARCH_PATTERN", Regexp.new(search_pattern))
|
44
|
-
klass.const_set("VERIFY_PATTERN", Regexp.new(verify_pattern))
|
45
|
-
|
46
|
-
klass.const_set("VALIDATION", tracking_info[:validation])
|
47
|
-
klass.const_set("ADDITIONAL", tracking_info[:additional])
|
48
|
-
|
49
|
-
return klass
|
50
|
-
end
|
51
|
-
|
52
|
-
def register_class(klass, tracking_name)
|
53
|
-
klass_name = tracking_name.gsub(/[^0-9A-Za-z]/, '')
|
54
|
-
return TrackingNumber.const_set(klass_name, klass)
|
55
|
-
end
|
56
|
-
|
57
|
-
tracking_number_types = []
|
58
|
-
|
59
|
-
Dir.glob(File.join(File.dirname(__FILE__), "data/couriers/*.json")).each do |file|
|
60
|
-
courier_info = read_courier_info(file)
|
61
|
-
|
62
|
-
courier_info[:tracking_numbers].each do |tracking_info|
|
63
|
-
tracking_name = tracking_info[:name]
|
64
|
-
klass = create_class(klass, courier_info, tracking_info)
|
65
|
-
|
66
|
-
# Do some basic checks on the data file
|
67
|
-
throw 'missing test numbers' unless has_test_numbers?(tracking_info)
|
68
|
-
throw 'missing regex match groups' unless test_numbers_return_required_groups?(tracking_info, Regexp.new(klass::VERIFY_PATTERN))
|
69
|
-
|
70
|
-
const = register_class(klass, tracking_name)
|
71
|
-
tracking_number_types.push(const)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
TrackingNumber.const_set("TYPES", tracking_number_types)
|
16
|
+
TrackingNumber::Loader.load_tracking_number_data
|
76
17
|
|
77
18
|
module TrackingNumber
|
78
19
|
def self.search(body)
|
@@ -21,13 +21,6 @@ class TrackingNumberMetaTest < Minitest::Test
|
|
21
21
|
|
22
22
|
describe "[#{tracking_info[:name]}]" do
|
23
23
|
tracking_info[:test_numbers][:valid].each do |valid_number|
|
24
|
-
|
25
|
-
should "validate #{valid_number} with #{klass_name}" do
|
26
|
-
t = klass.new(valid_number)
|
27
|
-
assert_equal courier_code, t.carrier
|
28
|
-
assert t.valid?, "should be valid"
|
29
|
-
end
|
30
|
-
|
31
24
|
should "detect #{valid_number} as #{klass_name}" do
|
32
25
|
#TODO fix this multiple matching thing
|
33
26
|
matches = TrackingNumber.search(valid_number)
|
@@ -45,47 +38,53 @@ class TrackingNumberMetaTest < Minitest::Test
|
|
45
38
|
should_detect_number_variants(valid_number, "TrackingNumber::#{klass_name}".constantize)
|
46
39
|
end
|
47
40
|
|
48
|
-
|
49
|
-
|
50
|
-
assert_equal courier_info[:courier_code].to_sym, t.courier_code
|
51
|
-
assert_equal courier_info[:courier_code].to_sym, t.courier_code
|
52
|
-
end
|
41
|
+
context "number test" do
|
42
|
+
tracking_number = klass.new(valid_number)
|
53
43
|
|
54
|
-
|
55
|
-
|
44
|
+
should "validate #{valid_number} with #{klass_name}" do
|
45
|
+
assert_equal courier_code, tracking_number.carrier
|
46
|
+
assert tracking_number.valid?, "should be valid"
|
47
|
+
end
|
56
48
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
assert_equal
|
49
|
+
should "return correct courier code on #{valid_number} when calling #courier_code" do
|
50
|
+
tracking_number = klass.new(valid_number)
|
51
|
+
assert_equal courier_info[:courier_code].to_sym, tracking_number.courier_code
|
52
|
+
assert_equal courier_info[:courier_code].to_sym,tracking_number.courier_code
|
61
53
|
end
|
62
|
-
end
|
63
54
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
55
|
+
should "return correct courier name on #{valid_number} when calling #courier_name" do
|
56
|
+
if (tracking_number.matching_additional["Courier"])
|
57
|
+
assert_equal tracking_number.matching_additional["Courier"][:courier], tracking_number.courier_name
|
58
|
+
else
|
59
|
+
assert_equal courier_name, tracking_number.courier_name
|
60
|
+
end
|
61
|
+
end
|
69
62
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
63
|
+
should "not throw an error when calling #service_type on #{valid_number}" do
|
64
|
+
service_type = tracking_number.service_type
|
65
|
+
assert service_type.is_a?(String) || service_type.nil?
|
66
|
+
end
|
74
67
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
end
|
68
|
+
should "not throw an error when calling #destination on #{valid_number}" do
|
69
|
+
assert tracking_number.destination_zip.is_a?(String) || tracking_number.destination_zip.nil?
|
70
|
+
end
|
79
71
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
72
|
+
should "not throw an error when calling #shipper on #{valid_number}" do
|
73
|
+
t = klass.new(valid_number)
|
74
|
+
assert tracking_number.shipper_id.is_a?(String) || tracking_number.shipper_id.nil?
|
75
|
+
end
|
76
|
+
|
77
|
+
should "not throw an error when calling #package_type on #{valid_number}" do
|
78
|
+
t = klass.new(valid_number)
|
79
|
+
assert tracking_number.package_type.is_a?(String) || tracking_number.package_type.nil?
|
80
|
+
end
|
81
|
+
|
82
|
+
should "not throw an error when calling #decode on #{valid_number}" do
|
83
|
+
t = klass.new(valid_number)
|
84
|
+
decode = tracking_number.decode
|
85
|
+
assert decode.is_a?(Hash)
|
86
|
+
end
|
84
87
|
|
85
|
-
should "not throw an error when calling #decode on #{valid_number}" do
|
86
|
-
t = klass.new(valid_number)
|
87
|
-
decode = t.decode
|
88
|
-
assert decode.is_a?(Hash)
|
89
88
|
end
|
90
89
|
end
|
91
90
|
|
@@ -64,6 +64,11 @@ class TrackingNumberTest < Minitest::Test
|
|
64
64
|
should "report correct no package info" do
|
65
65
|
assert_nil tracking_number.package_type
|
66
66
|
end
|
67
|
+
|
68
|
+
should "have valid tracking url" do
|
69
|
+
assert tracking_number.tracking_url, "Tracking url should not be blank"
|
70
|
+
assert tracking_number.tracking_url.include?(tracking_number.tracking_number), "Should include tracking number in the url"
|
71
|
+
end
|
67
72
|
end
|
68
73
|
|
69
74
|
context "tracking number additional data for s10" do
|
@@ -112,6 +117,11 @@ class TrackingNumberTest < Minitest::Test
|
|
112
117
|
should "report correct no package info" do
|
113
118
|
assert_nil tracking_number.package_type
|
114
119
|
end
|
120
|
+
|
121
|
+
should "have valid tracking url" do
|
122
|
+
assert tracking_number.tracking_url, "Tracking url should not be blank"
|
123
|
+
assert tracking_number.tracking_url.include?(tracking_number.tracking_number), "Should include tracking number in the url"
|
124
|
+
end
|
115
125
|
end
|
116
126
|
|
117
127
|
context "tracking number additional data for USPS 34v2" do
|
@@ -136,5 +146,10 @@ class TrackingNumberTest < Minitest::Test
|
|
136
146
|
should "report correct no package info" do
|
137
147
|
assert_nil tracking_number.package_type
|
138
148
|
end
|
149
|
+
|
150
|
+
should "have valid tracking url" do
|
151
|
+
assert tracking_number.tracking_url, "Tracking url should not be blank"
|
152
|
+
assert tracking_number.tracking_url.include?(tracking_number.tracking_number), "Should include tracking number in the url"
|
153
|
+
end
|
139
154
|
end
|
140
155
|
end
|
data/tracking_number.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tracking_number
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Keen
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -132,6 +132,7 @@ extra_rdoc_files:
|
|
132
132
|
- LICENSE.txt
|
133
133
|
files:
|
134
134
|
- ".document"
|
135
|
+
- ".github/workflows/ruby.yml"
|
135
136
|
- ".gitignore"
|
136
137
|
- ".gitmodules"
|
137
138
|
- ".travis.yml"
|
@@ -139,7 +140,6 @@ files:
|
|
139
140
|
- LICENSE.txt
|
140
141
|
- README.md
|
141
142
|
- Rakefile
|
142
|
-
- lib/checksum_validations.rb
|
143
143
|
- lib/data/couriers/amazon.json
|
144
144
|
- lib/data/couriers/dhl.json
|
145
145
|
- lib/data/couriers/fedex.json
|
@@ -150,7 +150,9 @@ files:
|
|
150
150
|
- lib/tracking_number.rb
|
151
151
|
- lib/tracking_number/active_model_validator.rb
|
152
152
|
- lib/tracking_number/base.rb
|
153
|
+
- lib/tracking_number/checksum_validations.rb
|
153
154
|
- lib/tracking_number/info.rb
|
155
|
+
- lib/tracking_number/loader.rb
|
154
156
|
- lib/tracking_number/unknown.rb
|
155
157
|
- lib/tracking_number/version.rb
|
156
158
|
- test/active_model_validator_test.rb
|
@@ -162,7 +164,7 @@ homepage: http://github.com/jkeen/tracking_number
|
|
162
164
|
licenses:
|
163
165
|
- MIT
|
164
166
|
metadata: {}
|
165
|
-
post_install_message:
|
167
|
+
post_install_message:
|
166
168
|
rdoc_options: []
|
167
169
|
require_paths:
|
168
170
|
- lib
|
@@ -177,9 +179,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
177
179
|
- !ruby/object:Gem::Version
|
178
180
|
version: '0'
|
179
181
|
requirements: []
|
180
|
-
|
181
|
-
|
182
|
-
signing_key:
|
182
|
+
rubygems_version: 3.1.4
|
183
|
+
signing_key:
|
183
184
|
specification_version: 4
|
184
185
|
summary: Identifies valid tracking numbers
|
185
|
-
test_files:
|
186
|
+
test_files:
|
187
|
+
- test/active_model_validator_test.rb
|
188
|
+
- test/test_helper.rb
|
189
|
+
- test/tracking_number_meta_test.rb
|
190
|
+
- test/tracking_number_test.rb
|
data/lib/checksum_validations.rb
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
module ChecksumValidations
|
2
|
-
class << self
|
3
|
-
def validates_s10?(sequence, check_digit, extras = {})
|
4
|
-
weighting = [8,6,4,2,3,5,9,7]
|
5
|
-
|
6
|
-
total = 0
|
7
|
-
sequence.chars.to_a.zip(weighting).each do |(a,b)|
|
8
|
-
total += a.to_i * b.to_i
|
9
|
-
end
|
10
|
-
|
11
|
-
remainder = total % 11
|
12
|
-
check = case remainder
|
13
|
-
when 1
|
14
|
-
0
|
15
|
-
when 0
|
16
|
-
5
|
17
|
-
else
|
18
|
-
11 - remainder
|
19
|
-
end
|
20
|
-
|
21
|
-
return check.to_i == check_digit.to_i
|
22
|
-
end
|
23
|
-
|
24
|
-
def validates_sum_product_with_weightings_and_modulo?(sequence, check_digit, extras = {})
|
25
|
-
weighting = extras[:weightings] || []
|
26
|
-
|
27
|
-
total = 0
|
28
|
-
sequence.chars.to_a.zip(weighting).each do |(a,b)|
|
29
|
-
total += a.to_i * b
|
30
|
-
end
|
31
|
-
return (total % extras[:modulo1] % extras[:modulo2]) == check_digit.to_i
|
32
|
-
end
|
33
|
-
|
34
|
-
def validates_mod10?(sequence, check_digit, extras = {})
|
35
|
-
total = 0
|
36
|
-
sequence.chars.each_with_index do |c, i|
|
37
|
-
x = if c[/[0-9]/] # numeric
|
38
|
-
c.to_i
|
39
|
-
else
|
40
|
-
(c[0].ord - 3) % 10
|
41
|
-
end
|
42
|
-
|
43
|
-
if extras[:odds_multiplier] && i.odd?
|
44
|
-
x *= extras[:odds_multiplier].to_i
|
45
|
-
elsif extras[:evens_multiplier] && i.even?
|
46
|
-
x *= extras[:evens_multiplier].to_i
|
47
|
-
end
|
48
|
-
|
49
|
-
total += x
|
50
|
-
end
|
51
|
-
|
52
|
-
check = (total % 10)
|
53
|
-
check = (10 - check) unless (check.zero?)
|
54
|
-
|
55
|
-
return (check.to_i == check_digit.to_i)
|
56
|
-
end
|
57
|
-
|
58
|
-
def validates_mod7?(sequence, check_digit, extras = {})
|
59
|
-
# standard mod 7 check
|
60
|
-
return true if sequence.to_i % 7 == check_digit.to_i
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|