tracking_number 0.10.5 → 1.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,34 +0,0 @@
1
- module TrackingNumber
2
- class OnTrac < Base
3
- SEARCH_PATTERN = /(\b(C\s*)([0-9]\s*){14,14}\b)/
4
- VERIFY_PATTERN = /^(C[0-9]{13,13})([0-9])$/
5
- def carrier
6
- :ontrac
7
- end
8
-
9
- def matches
10
- self.tracking_number.scan(VERIFY_PATTERN).flatten
11
- end
12
-
13
- def valid_checksum?
14
- # checksum calculation is the same as UPS
15
- sequence, check_digit = matches
16
-
17
- total = 0
18
- sequence.chars.each_with_index do |c, i|
19
- x = if c[/[0-9]/] # numeric
20
- c.to_i
21
- else
22
- (c[0].ord - 3) % 10
23
- end
24
- x *= 2 if i.odd?
25
- total += x
26
- end
27
-
28
- check = (total % 10)
29
- check = (10 - check) unless (check.zero?)
30
-
31
- return (check.to_i == check_digit.to_i)
32
- end
33
- end
34
- end
@@ -1,108 +0,0 @@
1
- module TrackingNumber
2
- class UPS < Base
3
- SEARCH_PATTERN = /(\b1\s*Z\s*(\w\s*){16,16}\b)/
4
- VERIFY_PATTERN = /^1Z(\w{15,15})(\w)$/
5
-
6
- def carrier
7
- :ups
8
- end
9
-
10
- def matches
11
- self.tracking_number.scan(VERIFY_PATTERN).flatten
12
- end
13
-
14
- def valid_checksum?
15
- sequence = tracking_number.slice(2...17)
16
- check_digit = tracking_number.slice(17, 18)
17
-
18
- total = 0
19
- sequence.chars.each_with_index do |c, i|
20
- x = if c[/[0-9]/] # numeric
21
- c.to_i
22
- else
23
- (c[0].ord - 3) % 10
24
- end
25
- x *= 2 if i.odd?
26
- total += x
27
- end
28
-
29
- check = (total % 10)
30
- check = (10 - check) unless (check.zero?)
31
-
32
- return (check.to_i == check_digit.to_i)
33
- end
34
-
35
- def decode
36
- {:shipper_account => self.tracking_number.to_s.slice(2...8),
37
- :service_type => self.tracking_number.to_s.slice(8...10),
38
- :package_identifier => self.tracking_number.to_s.slice(10...17),
39
- :check_digit => self.tracking_number.to_s.slice(17, 18)
40
- }
41
- end
42
-
43
- def service_type
44
- case decode[:service_type]
45
- when "01"
46
- "UPS United States Next Day Air (Red)"
47
- when "02"
48
- "UPS United States Second Day Air (Blue)"
49
- when "03"
50
- "UPS United States Ground"
51
- when "12"
52
- "UPS United States Third Day Select"
53
- when "13"
54
- "UPS United States Next Day Air Saver (Red Saver)"
55
- when "15"
56
- "UPS United States Next Day Air Early A.M."
57
- when "22"
58
- "UPS United States Ground - Returns Plus - Three Pickup Attempts"
59
- when "32"
60
- "UPS United States Next Day Air Early A.M. - COD"
61
- when "33"
62
- "UPS United States Next Day Air Early A.M. - Saturday Delivery, COD"
63
- when "41"
64
- "UPS United States Next Day Air Early A.M. - Saturday Delivery"
65
- when "42"
66
- "UPS United States Ground - Signature Required"
67
- when "44"
68
- "UPS United States Next Day Air - Saturday Delivery"
69
- when "66"
70
- "UPS United States Worldwide Express"
71
- when "72"
72
- "UPS United States Ground - Collect on Delivery"
73
- when "78"
74
- "UPS United States Ground - Returns Plus - One Pickup Attempt"
75
- when "90"
76
- "UPS United States Ground - Returns - UPS Prints and Mails Label"
77
- when "A0"
78
- "UPS United States Next Day Air Early A.M. - Adult Signature Required"
79
- when "A1"
80
- "UPS United States Next Day Air Early A.M. - Saturday Delivery, Adult Signature Required"
81
- when "A2"
82
- "UPS United States Next Day Air - Adult Signature Required"
83
- when "A8"
84
- "UPS United States Ground - Adult Signature Required"
85
- when "A9"
86
- "UPS United States Next Day Air Early A.M. - Adult Signature Required, COD"
87
- when "AA"
88
- "UPS United States Next Day Air Early A.M. - Saturday Delivery, Adult Signature Required, COD"
89
- end
90
- end
91
- end
92
-
93
- class UPSTest < UPS
94
- # Easypost UPS test numbers as described here:
95
- # https://www.easypost.com/docs/api#tracking (scroll down a bit).
96
- SEARCH_PATTERN = /^EZ(\d)00000000\1$/
97
- VERIFY_PATTERN = SEARCH_PATTERN
98
-
99
- def matches
100
- self.tracking_number.scan(VERIFY_PATTERN).flatten
101
- end
102
-
103
- def valid_checksum?
104
- sequence = tracking_number.scan(/[a-zA-Z0-9]+/).flatten.join
105
- return sequence =~ /EZ(\d)00000000\1/
106
- end
107
- end
108
- end
@@ -1,166 +0,0 @@
1
- module TrackingNumber
2
- class USPS < Base
3
- def carrier
4
- :usps
5
- end
6
- end
7
-
8
- class USPS91 < USPS
9
- SEARCH_PATTERN = [/(\b(?:420\s*\d{5})?9\s*[1-5]\s*(?:(?:(?:[0-9]\s*){20}\b)|(?:(?:[0-9]\s*){24}\b)))/, /(\b([0-9]\s*){20}\b)/]
10
- VERIFY_PATTERN = /^(?:420\d{5})?(9[1-5](?:[0-9]{19}|[0-9]{23}))([0-9])$/
11
-
12
- # Sometimes these numbers will appear without the leading 91, 93, or 94, though, so we need to account for that case
13
-
14
- def decode
15
- # Application ID: 91, 93, 94 or 95
16
- # Service Code: 2 Digits
17
- # Mailer Id: 8 Digits
18
- # Package Id: 9 Digits
19
- # Checksum: 1 Digit
20
-
21
- base_tracking_number = self.tracking_number.to_s.gsub(/^420\d{5}/, '')
22
-
23
- {:application_id => base_tracking_number.to_s.slice(0...2),
24
- :service_code => base_tracking_number.to_s.slice(2...4),
25
- :mailer_id => base_tracking_number.to_s.slice(4...12),
26
- :package_identifier => base_tracking_number.to_s.slice(12...21),
27
- :check_digit => base_tracking_number.slice(21...22)
28
- }
29
- end
30
-
31
- def matches
32
- if self.tracking_number =~ /^(420\d{5})?9[1-5]/
33
- self.tracking_number.scan(VERIFY_PATTERN).flatten
34
- else
35
- "91#{self.tracking_number}".scan(VERIFY_PATTERN).flatten
36
- end
37
- end
38
-
39
- def valid_checksum?
40
- if self.tracking_number =~ /^(420\d{5})?9[1-5]/
41
- return true if weighted_usps_checksum_valid?(tracking_number)
42
- else
43
- if weighted_usps_checksum_valid?("91#{self.tracking_number}")
44
- # set the tracking number to the 91 format if it passes this test
45
- self.tracking_number = "91#{self.tracking_number}"
46
- return true
47
- end
48
- end
49
- end
50
-
51
- private
52
-
53
- def weighted_usps_checksum_valid?(sequence)
54
- chars = sequence.gsub(/^420\d{5}/, '').chars.to_a
55
- check_digit = chars.pop
56
-
57
- total = 0
58
- chars.reverse.each_with_index do |c, i|
59
- x = c.to_i
60
- x *= 3 if i.even?
61
-
62
- total += x
63
- end
64
-
65
- check = total % 10
66
- check = 10 - check unless (check.zero?)
67
- return true if check == check_digit.to_i
68
- end
69
- end
70
-
71
- class USPS20 < USPS
72
- # http://www.usps.com/cpim/ftp/pubs/pub109.pdf (Publication 109. Extra Services Technical Guide, pg. 19)
73
- # http://www.usps.com/cpim/ftp/pubs/pub91.pdf (Publication 91. Confirmation Services Technical Guide pg. 38)
74
-
75
- SEARCH_PATTERN = /(\b([0-9]\s*){20,20}\b)/
76
- VERIFY_PATTERN = /^([0-9]{2,2})([0-9]{9,9})([0-9]{8,8})([0-9])$/
77
-
78
- def matches
79
- self.tracking_number.scan(VERIFY_PATTERN).flatten
80
- end
81
-
82
- def decode
83
- {:service_code => self.tracking_number.to_s.slice(0...2),
84
- :mailer_id => self.tracking_number.to_s.slice(2...11),
85
- :package_identifier => self.tracking_number.to_s.slice(11...19),
86
- :check_digit => self.tracking_number.slice(19...20)
87
- }
88
- end
89
-
90
- def service_type
91
- case decode[:service_code]
92
- when "71"
93
- "Certified Mail"
94
- when "73"
95
- "Insured Mail"
96
- when "77"
97
- "Registered Mail"
98
- when "81"
99
- "Return Receipt for Merchandise"
100
- end
101
- end
102
-
103
- def valid_checksum?
104
- chars = tracking_number.chars.to_a
105
- check_digit = chars.pop
106
-
107
- total = 0
108
- chars.reverse.each_with_index do |c, i|
109
- x = c.to_i
110
- x *= 3 if i.even?
111
- total += x
112
- end
113
-
114
- check = total % 10
115
- check = 10 - check unless (check.zero?)
116
- return true if check == check_digit.to_i
117
- end
118
- end
119
-
120
- class USPS13 < USPS
121
- SEARCH_PATTERN = /(\b([A-Z]\s*){2,2}([0-9]\s*){9,9}([A-Z]\s*){2,2}\b)/
122
- VERIFY_PATTERN = /^([A-Z]{2,2})([0-9]{9,9})([A-Z]{2,2})$/
123
-
124
- def matches
125
- self.tracking_number.scan(VERIFY_PATTERN).flatten
126
- end
127
-
128
- def valid_checksum?
129
- sequence = tracking_number.scan(/[0-9]+/).flatten.join
130
- chars = sequence.chars.to_a
131
- check_digit = chars.pop.to_i
132
-
133
- sum = 0
134
- chars.zip([8,6,4,2,3,5,9,7]).each do |pair|
135
- sum += (pair[0].to_i * pair[1].to_i)
136
- end
137
-
138
- remainder = sum % 11
139
- check = case remainder
140
- when 1
141
- 0
142
- when 0
143
- 5
144
- else
145
- 11 - remainder
146
- end
147
-
148
- return check == check_digit
149
- end
150
- end
151
-
152
- class USPSTest < USPS
153
- # USPS Test Number From Easypost. IE: 9499 9071 2345 6123 4567 81
154
- SEARCH_PATTERN = /(\b([0-9]\s*){22,22}\b)/
155
- VERIFY_PATTERN = SEARCH_PATTERN
156
-
157
- def matches
158
- self.tracking_number.scan(VERIFY_PATTERN).flatten
159
- end
160
-
161
- def valid_checksum?
162
- sequence = tracking_number.scan(/[0-9]+/).flatten.join
163
- return sequence == "9499907123456123456781"
164
- end
165
- end
166
- end
@@ -1,35 +0,0 @@
1
- require 'test_helper'
2
-
3
- class DHLTrackingNumberTest < Minitest::Test
4
- context "DHLExpressAir tracking number" do
5
- ["73891051146"].each do |valid_number|
6
- should "return dhl for #{valid_number}" do
7
- should_be_valid_number(valid_number, TrackingNumber::DHLExpressAir, :dhl)
8
- end
9
-
10
- should "fail on check digit changes on #{valid_number}" do
11
- should_fail_on_check_digit_changes(valid_number)
12
- end
13
-
14
- should "detect #{valid_number} regardless of spacing" do
15
- should_detect_number_variants(valid_number, TrackingNumber::DHLExpressAir)
16
- end
17
- end
18
- end
19
-
20
- context "DHLExpress tracking numbers" do
21
- ["3318810025", "8487135506", "3318810036", "3318810014"].each do |valid_number|
22
- should "return dhl for #{valid_number}" do
23
- should_be_valid_number(valid_number, TrackingNumber::DHLExpress, :dhl)
24
- end
25
-
26
- should "fail on check digit changes on #{valid_number}" do
27
- should_fail_on_check_digit_changes(valid_number)
28
- end
29
-
30
- should "detect #{valid_number} regardless of spacing" do
31
- should_detect_number_variants(valid_number, TrackingNumber::DHLExpress)
32
- end
33
- end
34
- end
35
- end
@@ -1,75 +0,0 @@
1
- require 'test_helper'
2
-
3
- class FedExTrackingNumberTest < Minitest::Test
4
- context "a FedEx tracking number" do
5
- ["986578788855", "477179081230", "799531274483", "790535312317", "974367662710"].each do |valid_number|
6
- should "return fedex express for #{valid_number}" do
7
- should_be_valid_number(valid_number, TrackingNumber::FedExExpress, :fedex)
8
- end
9
-
10
- should "fail on check digit changes on #{valid_number}" do
11
- should_fail_on_check_digit_changes(valid_number)
12
- end
13
-
14
- should "detect #{valid_number} regardless of spacing" do
15
- should_detect_number_variants(valid_number, TrackingNumber::FedExExpress)
16
- end
17
- end
18
-
19
- ["9611020987654312345672"].each do |valid_number|
20
- should "return fedex 96 for #{valid_number}" do
21
- should_be_valid_number(valid_number, TrackingNumber::FedExGround96, :fedex)
22
- end
23
-
24
- should "fail on check digit changes on #{valid_number}" do
25
- should_fail_on_check_digit_changes(valid_number)
26
- end
27
-
28
- should "detect #{valid_number} regardless of spacing" do
29
- should_detect_number_variants(valid_number, TrackingNumber::FedExGround96)
30
- end
31
- end
32
-
33
- ["0414 4176 0228 964", "5682 8361 0012 000", "5682 8361 0012 734"].each do |valid_number|
34
- should "return fedex ground for #{valid_number}" do
35
- should_be_valid_number(valid_number, TrackingNumber::FedExGround, :fedex)
36
- end
37
-
38
- should "fail on check digit changes on #{valid_number}" do
39
- should_fail_on_check_digit_changes(valid_number)
40
- end
41
-
42
- should "detect #{valid_number} regardless of spacing" do
43
- should_detect_number_variants(valid_number, TrackingNumber::FedExGround)
44
- end
45
- end
46
-
47
- ["00 0123 4500 0000 0027"].each do |valid_number|
48
- should "return fedex sscc18 for #{valid_number}" do
49
- should_be_valid_number(valid_number, TrackingNumber::FedExGround18, :fedex)
50
- end
51
-
52
- should "fail on check digit changes on #{valid_number}" do
53
- should_fail_on_check_digit_changes(valid_number)
54
- end
55
-
56
- should "detect #{valid_number} regardless of spacing" do
57
- should_detect_number_variants(valid_number, TrackingNumber::FedExGround18)
58
- end
59
- end
60
-
61
- ['61299998820821171811', '9261292700768711948021'].each do |valid_number|
62
- should "return fedex smart post for #{valid_number}" do
63
- should_be_valid_number(valid_number, TrackingNumber::FedExSmartPost, :fedex)
64
- end
65
-
66
- should "fail on check digit changes on #{valid_number}" do
67
- should_fail_on_check_digit_changes(valid_number)
68
- end
69
-
70
- should "detect #{valid_number} regardless of spacing" do
71
- should_detect_number_variants(valid_number, TrackingNumber::FedExSmartPost)
72
- end
73
- end
74
- end
75
- end
@@ -1,24 +0,0 @@
1
- require 'test_helper'
2
-
3
- class OnTracTrackingNumberTest < Minitest::Test
4
- context "an OnTrac tracking number" do
5
- ["C11031500001879", "C10999911320231"].each do |valid_number|
6
- should "return ontrac for #{valid_number}" do
7
- should_be_valid_number(valid_number, TrackingNumber::OnTrac, :ontrac)
8
- end
9
-
10
- should "fail on check digit changes on #{valid_number}" do
11
- should_fail_on_check_digit_changes(valid_number)
12
- end
13
-
14
- should "detect #{valid_number} regardless of spacing" do
15
- should_detect_number_variants(valid_number, TrackingNumber::OnTrac)
16
- end
17
- end
18
-
19
- should "not detect an invalid number" do
20
- results = TrackingNumber::OnTrac.search("C10999911320230")
21
- assert_equal 0, results.size
22
- end
23
- end
24
- end