tracking_number 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +0 -2
- data/lib/data/couriers/amazon.json +28 -0
- data/lib/data/couriers/dhl.json +50 -0
- data/lib/data/couriers/fedex.json +269 -0
- data/lib/data/couriers/ontrac.json +35 -0
- data/lib/data/couriers/s10.json +1435 -0
- data/lib/data/couriers/ups.json +139 -0
- data/lib/data/couriers/usps.json +140 -0
- data/lib/tracking_number/version.rb +1 -1
- data/tracking_number.gemspec +17 -0
- metadata +9 -3
- data/lib/tasks/stats.rake +0 -90
@@ -0,0 +1,139 @@
|
|
1
|
+
{
|
2
|
+
"name": "UPS",
|
3
|
+
"courier_code": "ups",
|
4
|
+
"tracking_numbers": [
|
5
|
+
{
|
6
|
+
"name": "UPS",
|
7
|
+
"regex": [
|
8
|
+
"\\s*1\\s*Z\\s*(?<SerialNumber>",
|
9
|
+
"(?<ShipperId>(?:[A-Z0-9]\\s*){6,6})",
|
10
|
+
"(?<ServiceType>(?:[A-Z0-9]\\s*){2,2})",
|
11
|
+
"(?<PackageId>(?:[A-Z0-9]\\s*){7,7}))",
|
12
|
+
"(?<CheckDigit>[A-Z0-9]\\s*)"
|
13
|
+
],
|
14
|
+
"validation": {
|
15
|
+
"checksum": {
|
16
|
+
"name": "mod10",
|
17
|
+
"evens_multiplier": 1,
|
18
|
+
"odds_multiplier": 2
|
19
|
+
}
|
20
|
+
},
|
21
|
+
"tracking_url": "https://wwwapps.ups.com/WebTracking/track?track=yes&trackNums=%s",
|
22
|
+
"additional": [
|
23
|
+
{
|
24
|
+
"name": "Service Type",
|
25
|
+
"regex_group_name": "ServiceType",
|
26
|
+
"lookup": [
|
27
|
+
{
|
28
|
+
"matches": "01",
|
29
|
+
"name": "UPS United States Next Day Air (Red)"
|
30
|
+
},
|
31
|
+
{
|
32
|
+
"matches": "02",
|
33
|
+
"name": "UPS United States Second Day Air (Blue)"
|
34
|
+
},
|
35
|
+
{
|
36
|
+
"matches": "03",
|
37
|
+
"name": "UPS United States Ground"
|
38
|
+
},
|
39
|
+
{
|
40
|
+
"matches": "12",
|
41
|
+
"name": "UPS United States Third Day Select"
|
42
|
+
},
|
43
|
+
{
|
44
|
+
"matches": "13",
|
45
|
+
"name": "UPS United States Next Day Air Saver (Red Saver)"
|
46
|
+
},
|
47
|
+
{
|
48
|
+
"matches": "15",
|
49
|
+
"name": "UPS United States Next Day Air Early A.M."
|
50
|
+
},
|
51
|
+
{
|
52
|
+
"matches": "22",
|
53
|
+
"name": "UPS United States Ground - Returns Plus - Three Pickup Attempts"
|
54
|
+
},
|
55
|
+
{
|
56
|
+
"matches": "32",
|
57
|
+
"name": "UPS United States Next Day Air Early A.M. - COD"
|
58
|
+
},
|
59
|
+
{
|
60
|
+
"matches": "33",
|
61
|
+
"name": "UPS United States Next Day Air Early A.M. - Saturday Delivery, COD"
|
62
|
+
},
|
63
|
+
{
|
64
|
+
"matches": "41",
|
65
|
+
"name": "UPS United States Next Day Air Early A.M. - Saturday Delivery"
|
66
|
+
},
|
67
|
+
{
|
68
|
+
"matches": "42",
|
69
|
+
"name": "UPS United States Ground - Signature Required"
|
70
|
+
},
|
71
|
+
{
|
72
|
+
"matches": "44",
|
73
|
+
"name": "UPS United States Next Day Air - Saturday Delivery"
|
74
|
+
},
|
75
|
+
{
|
76
|
+
"matches": "66",
|
77
|
+
"name": "UPS United States Worldwide Express"
|
78
|
+
},
|
79
|
+
{
|
80
|
+
"matches": "72",
|
81
|
+
"name": "UPS United States Ground - Collect on Delivery"
|
82
|
+
},
|
83
|
+
{
|
84
|
+
"matches": "78",
|
85
|
+
"name": "UPS United States Ground - Returns Plus - One Pickup Attempt"
|
86
|
+
},
|
87
|
+
{
|
88
|
+
"matches": "90",
|
89
|
+
"name": "UPS United States Ground - Returns - UPS Prints and Mails Label"
|
90
|
+
},
|
91
|
+
{
|
92
|
+
"matches": "A0",
|
93
|
+
"name": "UPS United States Next Day Air Early A.M. - Adult Signature Required"
|
94
|
+
},
|
95
|
+
{
|
96
|
+
"matches": "A1",
|
97
|
+
"name": "UPS United States Next Day Air Early A.M. - Saturday Delivery, Adult Signature Required"
|
98
|
+
},
|
99
|
+
{
|
100
|
+
"matches": "A2",
|
101
|
+
"name": "UPS United States Next Day Air - Adult Signature Required"
|
102
|
+
},
|
103
|
+
{
|
104
|
+
"matches": "A8",
|
105
|
+
"name": "UPS United States Ground - Adult Signature Required"
|
106
|
+
},
|
107
|
+
{
|
108
|
+
"matches": "A9",
|
109
|
+
"name": "UPS United States Next Day Air Early A.M. - Adult Signature Required, COD"
|
110
|
+
},
|
111
|
+
{
|
112
|
+
"matches": "AA",
|
113
|
+
"name": "UPS United States Next Day Air Early A.M. - Saturday Delivery, Adult Signature Required, COD"
|
114
|
+
},
|
115
|
+
{
|
116
|
+
"matches": "YW",
|
117
|
+
"name": "UPS SurePost - Delivered by the USPS"
|
118
|
+
}
|
119
|
+
]
|
120
|
+
}
|
121
|
+
],
|
122
|
+
"test_numbers": {
|
123
|
+
"valid": [
|
124
|
+
"1Z5R89390357567127",
|
125
|
+
"1Z879E930346834440",
|
126
|
+
"1Z410E7W0392751591",
|
127
|
+
"1Z8V92A70367203024",
|
128
|
+
" 1 Z 8 V 9 2 A 7 0 3 6 7 2 0 3 0 2 4 ",
|
129
|
+
"1ZXX3150YW44070023"
|
130
|
+
],
|
131
|
+
"invalid": [
|
132
|
+
"2Z5R89390357567127",
|
133
|
+
"1A5R89390357567127",
|
134
|
+
"1Z1111111111111111"
|
135
|
+
]
|
136
|
+
}
|
137
|
+
}
|
138
|
+
]
|
139
|
+
}
|
@@ -0,0 +1,140 @@
|
|
1
|
+
{
|
2
|
+
"name": "United States Postal Service",
|
3
|
+
"courier_code": "usps",
|
4
|
+
"tracking_numbers": [
|
5
|
+
{
|
6
|
+
"tracking_url": "https://m.usps.com/m/TrackConfirmAction_detail?tLabels=%s",
|
7
|
+
"name": "USPS 20",
|
8
|
+
"description": "20 digit USPS numbers",
|
9
|
+
"regex": [
|
10
|
+
"\\s*(?<SerialNumber>",
|
11
|
+
"(?<ServiceType>([0-9]\\s*){2})",
|
12
|
+
"(?<ShipperId>([0-9]\\s*){9})",
|
13
|
+
"(?<PackageId>([0-9]\\s*){8})",
|
14
|
+
")",
|
15
|
+
"(?<CheckDigit>[0-9]\\s*)"
|
16
|
+
],
|
17
|
+
"validation": {
|
18
|
+
"checksum": {
|
19
|
+
"name": "mod10",
|
20
|
+
"evens_multiplier": 3,
|
21
|
+
"odds_multiplier": 1
|
22
|
+
}
|
23
|
+
},
|
24
|
+
"test_numbers": {
|
25
|
+
"valid": [
|
26
|
+
"0307 1790 0005 2348 3741",
|
27
|
+
" 0 3 0 7 1 7 9 0 0 0 0 5 2 3 4 8 3 7 4 1 ",
|
28
|
+
"7112 3456 7891 2345 6787"
|
29
|
+
],
|
30
|
+
"invalid": [
|
31
|
+
"0307 1790 0005 2348 3742"
|
32
|
+
]
|
33
|
+
},
|
34
|
+
"additional": [
|
35
|
+
{
|
36
|
+
"name": "Service Type",
|
37
|
+
"regex_group_name": "ServiceType",
|
38
|
+
"lookup": [
|
39
|
+
{
|
40
|
+
"matches": "71",
|
41
|
+
"name": "Certified Mail"
|
42
|
+
},
|
43
|
+
{
|
44
|
+
"matches": "73",
|
45
|
+
"name": "Insured Mail"
|
46
|
+
},
|
47
|
+
{
|
48
|
+
"matches": "77",
|
49
|
+
"name": "Registered Mail"
|
50
|
+
},
|
51
|
+
{
|
52
|
+
"matches": "81",
|
53
|
+
"name": "Return Receipt For Merchanise"
|
54
|
+
}
|
55
|
+
]
|
56
|
+
}
|
57
|
+
]
|
58
|
+
},
|
59
|
+
{
|
60
|
+
"name": "USPS 34v2",
|
61
|
+
"description": "variation on 34 digit USPS IMpd numbers",
|
62
|
+
"regex": [
|
63
|
+
"\\s*(?<RoutingApplicationId>4\\s*2\\s*0\\s*)(?<DestinationZip>([0-9]\\s*){5})",
|
64
|
+
"(?<RoutingNumber>([0-9]\\s*){4})",
|
65
|
+
"(?<SerialNumber>",
|
66
|
+
"(?<ApplicationIdentifier>9\\s*[2345]\\s*)?",
|
67
|
+
"(?<ShipperId>([0-9]\\s*){8})",
|
68
|
+
"(?<PackageId>([0-9]\\s*){11})",
|
69
|
+
")",
|
70
|
+
"(?<CheckDigit>[0-9]\\s*)"
|
71
|
+
],
|
72
|
+
"validation": {
|
73
|
+
"checksum": {
|
74
|
+
"name": "mod10",
|
75
|
+
"evens_multiplier": 3,
|
76
|
+
"odds_multiplier": 1
|
77
|
+
}
|
78
|
+
},
|
79
|
+
"tracking_url": "https://m.usps.com/m/TrackConfirmAction_detail?tLabels=%s",
|
80
|
+
"test_numbers": {
|
81
|
+
"valid": [
|
82
|
+
"4201002334249200190132607600833457",
|
83
|
+
"4201028200009261290113185417468510",
|
84
|
+
" 4 2 0 1 0 2 8 2 0 0 0 0 9 2 6 1 2 9 0 1 1 3 1 8 5 4 1 7 4 6 8 5 1 0 "
|
85
|
+
],
|
86
|
+
"invalid": [
|
87
|
+
"4201028200009261290113185417468511"
|
88
|
+
]
|
89
|
+
}
|
90
|
+
},
|
91
|
+
{
|
92
|
+
"name": "USPS 91",
|
93
|
+
"description": "USPS now calls this the IMpd barcode format",
|
94
|
+
"regex": [
|
95
|
+
"\\s*(?:(?<RoutingApplicationId>4\\s*2\\s*0\\s*)(?<DestinationZip>([0-9]\\s*){5}))?",
|
96
|
+
"(?<SerialNumber>",
|
97
|
+
"(?<ApplicationIdentifier>9\\s*[12345]\\s*)?",
|
98
|
+
"(?<SCNC>([0-9]\\s*){2})",
|
99
|
+
"(?<ServiceType>([0-9]\\s*){2})",
|
100
|
+
"(?<ShipperId>([0-9]\\s*){8})",
|
101
|
+
"(?<PackageId>([0-9]\\s*){11}|([0-9]\\s*){7})",
|
102
|
+
")",
|
103
|
+
"(?<CheckDigit>[0-9]\\s*)"
|
104
|
+
],
|
105
|
+
"validation": {
|
106
|
+
"checksum": {
|
107
|
+
"name": "mod10",
|
108
|
+
"evens_multiplier": 3,
|
109
|
+
"odds_multiplier": 1
|
110
|
+
},
|
111
|
+
"serial_number_format": {
|
112
|
+
"prepend_if": {
|
113
|
+
"matches_regex": "^(?!9[1-5]).+",
|
114
|
+
"content": "91"
|
115
|
+
}
|
116
|
+
}
|
117
|
+
},
|
118
|
+
"tracking_url": "https://m.usps.com/m/TrackConfirmAction_detail?tLabels=%s",
|
119
|
+
"test_numbers": {
|
120
|
+
"valid": [
|
121
|
+
"420 22153 9101026837331000039521",
|
122
|
+
"7196 9010 7560 0307 7385",
|
123
|
+
"9505 5110 6960 5048 6006 24",
|
124
|
+
"9101 1234 5678 9000 0000 13",
|
125
|
+
"92748931507708513018050063",
|
126
|
+
"9400 1112 0108 0805 4830 16",
|
127
|
+
"9361 2898 7870 0317 6337 95",
|
128
|
+
" 9 3 6 1 2 8 9 8 7 8 7 0 0 3 1 7 6 3 3 7 9 5 ",
|
129
|
+
"9405803699300124287899"
|
130
|
+
],
|
131
|
+
"invalid": [
|
132
|
+
"61299998820821171811",
|
133
|
+
"9200000000000000000000",
|
134
|
+
"420000000000000000000000000000",
|
135
|
+
"420000009200000000000000000000"
|
136
|
+
]
|
137
|
+
}
|
138
|
+
}
|
139
|
+
]
|
140
|
+
}
|
data/tracking_number.gemspec
CHANGED
@@ -13,8 +13,25 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.extra_rdoc_files = [
|
14
14
|
"LICENSE.txt",
|
15
15
|
]
|
16
|
+
|
16
17
|
s.files = `git ls-files`.split("\n")
|
18
|
+
|
19
|
+
gem_dir = File.expand_path(File.dirname(__FILE__)) + "/"
|
20
|
+
|
21
|
+
`git submodule --quiet foreach pwd`.split($\).each do |submodule_path|
|
22
|
+
Dir.chdir(submodule_path.chomp) do
|
23
|
+
submodule_relative_path = submodule_path.sub gem_dir, ""
|
24
|
+
# issue git ls-files in submodule's directory and
|
25
|
+
# prepend the submodule path to create absolute file paths
|
26
|
+
|
27
|
+
`git ls-files -- couriers/*`.split($\).each do |filename|
|
28
|
+
s.files << "#{submodule_relative_path}/#{filename}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
17
33
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
34
|
+
|
18
35
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
36
|
s.require_paths = ["lib"]
|
20
37
|
s.homepage = %q{http://github.com/jkeen/tracking_number}
|
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.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Keen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-02-
|
11
|
+
date: 2018-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -140,7 +140,13 @@ files:
|
|
140
140
|
- README.md
|
141
141
|
- Rakefile
|
142
142
|
- lib/checksum_validations.rb
|
143
|
-
- lib/
|
143
|
+
- lib/data/couriers/amazon.json
|
144
|
+
- lib/data/couriers/dhl.json
|
145
|
+
- lib/data/couriers/fedex.json
|
146
|
+
- lib/data/couriers/ontrac.json
|
147
|
+
- lib/data/couriers/s10.json
|
148
|
+
- lib/data/couriers/ups.json
|
149
|
+
- lib/data/couriers/usps.json
|
144
150
|
- lib/tracking_number.rb
|
145
151
|
- lib/tracking_number/active_model_validator.rb
|
146
152
|
- lib/tracking_number/base.rb
|
data/lib/tasks/stats.rake
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
require 'terminal-table'
|
2
|
-
|
3
|
-
def courier_data
|
4
|
-
courier_data = Dir.glob(File.join(File.dirname(__FILE__), "../../lib/data/couriers/*.json")).collect do |file|
|
5
|
-
JSON.parse(File.read(file)).deep_symbolize_keys!
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
def all_number_groups
|
10
|
-
number_groups = []
|
11
|
-
courier_data.each do |courier_info|
|
12
|
-
courier_info[:tracking_numbers].each do |tracking_info|
|
13
|
-
test_number = tracking_info[:test_numbers][:valid].first
|
14
|
-
t = TrackingNumber.new(test_number)
|
15
|
-
# keys = t.decode.keys.select { |s| ![:serial_number, :check_digit].include?(s) }
|
16
|
-
number_groups << t.decode.keys
|
17
|
-
end
|
18
|
-
end
|
19
|
-
groups = number_groups.flatten.uniq.sort
|
20
|
-
end
|
21
|
-
|
22
|
-
def has_key?(tracking_numbers, key)
|
23
|
-
tracking_numbers = [tracking_numbers].flatten
|
24
|
-
tracking_numbers.first.decode[key]
|
25
|
-
end
|
26
|
-
|
27
|
-
def has_additional_key_info?(tracking_numbers, key)
|
28
|
-
tracking_numbers = [tracking_numbers].flatten
|
29
|
-
|
30
|
-
if key == :service_type
|
31
|
-
tracking_numbers.any? { |t| t.service_type }
|
32
|
-
elsif key == :shipping_container_type
|
33
|
-
tracking_numbers.any? { |t| t.package_type }
|
34
|
-
elsif key == :destination_zip
|
35
|
-
tracking_numbers.any? { |t| t.destination_zip }
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
|
40
|
-
desc "show stats for tracking number types"
|
41
|
-
task :stats do
|
42
|
-
rows = []
|
43
|
-
|
44
|
-
courier_data.each do |courier_info|
|
45
|
-
courier_name = courier_info[:name]
|
46
|
-
courier_code = courier_info[:courier_code].to_sym
|
47
|
-
|
48
|
-
courier_info[:tracking_numbers].each do |tracking_info|
|
49
|
-
tracking_type = tracking_info[:name]
|
50
|
-
|
51
|
-
if tracking_type == "S10"
|
52
|
-
country_count = tracking_info[:additional].detect { |r| r[:regex_group_name] == "CountryCode" }[:lookup].size
|
53
|
-
tracking_type = "S10 (#{country_count} types)"
|
54
|
-
end
|
55
|
-
|
56
|
-
tracking_numbers = tracking_info[:test_numbers][:valid].collect { |n| TrackingNumber.new(n) }
|
57
|
-
|
58
|
-
checksum_status = tracking_numbers.first.valid_checksum? &&
|
59
|
-
|
60
|
-
checksum = tracking_numbers.first.class.const_get(:VALIDATION)[:checksum]
|
61
|
-
if checksum
|
62
|
-
checksum_status = '✓'
|
63
|
-
else
|
64
|
-
checksum_status = ''
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
status = all_number_groups.collect do |key|
|
69
|
-
s = has_key?(tracking_numbers, key) ? '✓' : ''
|
70
|
-
s = has_additional_key_info?(tracking_numbers, key) ? '✓+' : s
|
71
|
-
|
72
|
-
s
|
73
|
-
end
|
74
|
-
|
75
|
-
rows << [tracking_type, checksum_status, *status]
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
additional_headers = all_number_groups.collect { |g|
|
80
|
-
if g.length > 10
|
81
|
-
g.to_s.split('_').join("_\n")
|
82
|
-
else
|
83
|
-
g
|
84
|
-
end
|
85
|
-
}
|
86
|
-
|
87
|
-
table = Terminal::Table.new :title => "Tracking Number Stats [✓ = information present in number, ✓+ = additional information available]", :headings => ['Tracking Number', 'Checksum', *additional_headers], :rows => rows
|
88
|
-
|
89
|
-
puts table
|
90
|
-
end
|