tracking_number 2.2.0 → 2.4.0
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/CHANGELOG.md +19 -0
- data/lib/data/couriers/dhl.json +74 -0
- data/lib/data/couriers/fedex.json +2 -4
- data/lib/data/couriers/usps.json +96 -1
- data/lib/tracking_number/base.rb +19 -15
- data/lib/tracking_number/checksum_validations.rb +7 -1
- data/lib/tracking_number/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c0ef2fa722ce7a2d9cc6cfaac9c5510ef7ac79074ba4e227f9554b8157da2ee
|
4
|
+
data.tar.gz: 3a5f46d4dc5027e8bf68c4f7cf0756851e284d29b499c38d4c264b57ebc61fc4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 404a19a4f9847ade5581c5ff7c0cf950fde208d773f81f6882715d44b4395f94fc505538d46b718ad0c7fbfcdf152e512619ca86372dc1021a524ab2614cd898
|
7
|
+
data.tar.gz: c4fbe1cf3637fea233106008bc31c1b555a63ea7e04588f08446d00a5d6dd3948daf744e078a74c6e96d7f257c51986fa8712db5f3b9e1e742e0ea9d61a6c63c
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
tracking_number changelog
|
2
2
|
|
3
|
+
# [2.4.0](https://github.com/jkeen/tracking_number/compare/v2.3.0...v2.4.0) (2025-08-21)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* update to tracking_number_data 1.9.0 ([f885bfd](https://github.com/jkeen/tracking_number/commit/f885bfd956ffacb22f38967754ec14551bca8d50))
|
9
|
+
|
10
|
+
# [2.3.0](https://github.com/jkeen/tracking_number/compare/v2.2.0...v2.3.0) (2025-08-21)
|
11
|
+
|
12
|
+
|
13
|
+
### Bug Fixes
|
14
|
+
|
15
|
+
* prevent error when lookup is balnk for an additional info group ([cce4ddd](https://github.com/jkeen/tracking_number/commit/cce4dddf1ec4b62baa684af24a8be96893fd33a6))
|
16
|
+
|
17
|
+
|
18
|
+
### Features
|
19
|
+
|
20
|
+
* add validation option to mod10 to validate in reverse ([3736b50](https://github.com/jkeen/tracking_number/commit/3736b5003d2cc4cbaec2db50f8b64add61897731))
|
21
|
+
|
3
22
|
# [2.2.0](https://github.com/jkeen/tracking_number/compare/v2.1.1...v2.2.0) (2025-06-24)
|
4
23
|
|
5
24
|
|
data/lib/data/couriers/dhl.json
CHANGED
@@ -89,6 +89,80 @@
|
|
89
89
|
"GR295117494011169045"
|
90
90
|
]
|
91
91
|
}
|
92
|
+
},
|
93
|
+
{
|
94
|
+
"name": "DHL E-Commerce (30)",
|
95
|
+
"id": "dhl_ecommerce_30",
|
96
|
+
"regex": [
|
97
|
+
"\\s*(?<RoutingApplicationId>4\\s*2\\s*0\\s*)(?<DestinationZip>([0-9]\\s*){5})",
|
98
|
+
"(?!\\s*9\\s*[1-5]\\b)",
|
99
|
+
"(?<SerialNumber>",
|
100
|
+
"(?<ServiceType>(9[2-5]\\s*))",
|
101
|
+
"(?<ShipperId>([0-9]\\s*){9})",
|
102
|
+
"(?<PackageId>([0-9]\\s*){10})",
|
103
|
+
")",
|
104
|
+
"(?<CheckDigit>[0-9]\\s*)"
|
105
|
+
],
|
106
|
+
"validation": {
|
107
|
+
"checksum": {
|
108
|
+
"name": "mod10",
|
109
|
+
"evens_multiplier": 3,
|
110
|
+
"odds_multiplier": 1,
|
111
|
+
"reverse": true
|
112
|
+
}
|
113
|
+
},
|
114
|
+
"tracking_url": "https://ecommerceportal.dhl.com/track?trackingnumber=%s",
|
115
|
+
"partners": [{
|
116
|
+
"description": "DHL eCommerce hands off to USPS for the last mile",
|
117
|
+
"partner_type": "carrier",
|
118
|
+
"partner_id": "usps_22",
|
119
|
+
"validation": {
|
120
|
+
"matches_all": [
|
121
|
+
{ "regex_group_name": "RoutingApplicationId", "matches": "420" },
|
122
|
+
{ "regex_group_name": "ServiceType", "matches_regex": "9[2345]" }
|
123
|
+
]
|
124
|
+
}
|
125
|
+
},
|
126
|
+
{
|
127
|
+
"description": "DHL eCommerce hands off to USPS for the last mile",
|
128
|
+
"partner_type": "carrier",
|
129
|
+
"partner_id": "usps_91",
|
130
|
+
"validation": {
|
131
|
+
"matches_all": [
|
132
|
+
{ "regex_group_name": "RoutingApplicationId", "matches": "420" },
|
133
|
+
{ "regex_group_name": "ServiceType", "matches_regex": "9[2345]" }
|
134
|
+
]
|
135
|
+
}
|
136
|
+
}],
|
137
|
+
"additional": [
|
138
|
+
{
|
139
|
+
"name": "Service Type",
|
140
|
+
"regex_group_name": "ServiceType",
|
141
|
+
"lookup": [
|
142
|
+
{ "matches": "92", "name": "USPS Tracking (Commercial)" },
|
143
|
+
{ "matches": "93", "name": "Collect on Delivery (COD)" },
|
144
|
+
{ "matches": "94", "name": "USPS Tracking" },
|
145
|
+
{ "matches": "95", "name": "Certified Mail" }
|
146
|
+
]
|
147
|
+
}
|
148
|
+
],
|
149
|
+
"test_numbers": {
|
150
|
+
"valid": [
|
151
|
+
"420902459261290336128704042634",
|
152
|
+
"420941179261290336128704062441",
|
153
|
+
"420926029261290336128704067248",
|
154
|
+
"420902729261290336128704124163",
|
155
|
+
"420950549261290336128704133837",
|
156
|
+
"420193809261290336128704280838",
|
157
|
+
"420900469261290336128704216936"
|
158
|
+
],
|
159
|
+
"invalid": [
|
160
|
+
"420941179261290336128704062442",
|
161
|
+
"420941179261290336128704062400",
|
162
|
+
"420941179261290336128704062422"
|
163
|
+
]
|
164
|
+
}
|
92
165
|
}
|
166
|
+
|
93
167
|
]
|
94
168
|
}
|
@@ -98,7 +98,7 @@
|
|
98
98
|
"(?<ApplicationIdentifier>9\\s*2\\s*)",
|
99
99
|
")?",
|
100
100
|
"(?<SerialNumber>",
|
101
|
-
"(?<SCNC>
|
101
|
+
"(?<SCNC>6\\s*1\\s*)",
|
102
102
|
"(?<ServiceType>2\\s*9\\s*)",
|
103
103
|
"(?<ShipperId>([0-9]\\s*){8})",
|
104
104
|
"(?<PackageId>([0-9]\\s*){11}|([0-9]\\s*){7})",
|
@@ -138,11 +138,9 @@
|
|
138
138
|
"tracking_url": "https://www.fedex.com/apps/fedextrack/?tracknumbers=%s",
|
139
139
|
"test_numbers": {
|
140
140
|
"valid": [
|
141
|
-
"61299998820821171811",
|
142
141
|
"9261292700768711948021",
|
143
142
|
"420 11213 92 6129098349792366623 8",
|
144
|
-
"92 6129098349792366623 8"
|
145
|
-
"6129098349792366623 8"
|
143
|
+
"92 6129098349792366623 8"
|
146
144
|
],
|
147
145
|
"invalid": [
|
148
146
|
"9261292700768711948020",
|
data/lib/data/couriers/usps.json
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
"courier_code": "usps",
|
4
4
|
"tracking_numbers": [
|
5
5
|
{
|
6
|
-
"tracking_url": "https://tools.usps.com/go/TrackConfirmAction?tLabels=%s",
|
7
6
|
"name": "USPS 20",
|
8
7
|
"id": "usps_20",
|
9
8
|
"description": "20 digit USPS numbers",
|
9
|
+
"tracking_url": "https://tools.usps.com/go/TrackConfirmAction?tLabels=%s",
|
10
10
|
"regex": [
|
11
11
|
"\\s*(?<SerialNumber>",
|
12
12
|
"(?<ServiceType>([0-9]\\s*){2})",
|
@@ -57,6 +57,76 @@
|
|
57
57
|
}
|
58
58
|
]
|
59
59
|
},
|
60
|
+
{
|
61
|
+
"name": "USPS 22",
|
62
|
+
"id": "usps_22",
|
63
|
+
"description": "22 digit USPS numbers",
|
64
|
+
"tracking_url": "https://tools.usps.com/go/TrackConfirmAction?tLabels=%s",
|
65
|
+
"regex": [
|
66
|
+
"\\s*((?<RoutingApplicationId>4\\s*2\\s*0\\s*)(?<DestinationZip>([0-9]\\s*){5}))?",
|
67
|
+
"(?<SerialNumber>",
|
68
|
+
"(?<ServiceType>(9\\s*[4-8]\\s*))",
|
69
|
+
"(?<ShipperId>([0-9]\\s*){9})",
|
70
|
+
"(?<PackageId>([0-9]\\s*){10})",
|
71
|
+
")",
|
72
|
+
"(?<CheckDigit>[0-9]\\s*)"
|
73
|
+
],
|
74
|
+
"validation": {
|
75
|
+
"checksum": {
|
76
|
+
"name": "mod10",
|
77
|
+
"evens_multiplier": 3,
|
78
|
+
"odds_multiplier": 1,
|
79
|
+
"reverse": true
|
80
|
+
}
|
81
|
+
},
|
82
|
+
"test_numbers": {
|
83
|
+
"valid": [
|
84
|
+
"420787459400111206206406260787",
|
85
|
+
"9400111206206406260787",
|
86
|
+
"9434611206206406227577",
|
87
|
+
"9434611206206407667136",
|
88
|
+
"9400111206206407628746",
|
89
|
+
"9400111206206407628845"
|
90
|
+
],
|
91
|
+
"invalid": [
|
92
|
+
"9434611206206407667131",
|
93
|
+
"9434611306206407667222",
|
94
|
+
"2334611306206407667222"
|
95
|
+
]
|
96
|
+
},
|
97
|
+
"partners": [{
|
98
|
+
"description": "DHL ECommerce uses USPS for last mile delivery",
|
99
|
+
"partner_type": "shipper",
|
100
|
+
"partner_id": "dhl_ecommerce_30",
|
101
|
+
"validation": {
|
102
|
+
"matches_all": [
|
103
|
+
{
|
104
|
+
"regex_group_name": "RoutingApplicationId",
|
105
|
+
"matches": "420"
|
106
|
+
},
|
107
|
+
{
|
108
|
+
"matches_regex": "9[24]",
|
109
|
+
"regex_group_name": "ServiceType"
|
110
|
+
}
|
111
|
+
]
|
112
|
+
}
|
113
|
+
}],
|
114
|
+
"additional": [
|
115
|
+
{
|
116
|
+
"name": "Service Type",
|
117
|
+
"regex_group_name": "ServiceType",
|
118
|
+
"lookup": [
|
119
|
+
{ "matches": "92", "name": "Signature Confirmation" },
|
120
|
+
{ "matches": "93", "name": "Collect on Delivery (COD)" },
|
121
|
+
{ "matches": "94", "name": "USPS Tracking" },
|
122
|
+
{ "matches": "95", "name": "Certified Mail" },
|
123
|
+
{ "matches": "96", "name": "Insured Mail" },
|
124
|
+
{ "matches": "97", "name": "Registered Mail" },
|
125
|
+
{ "matches": "98", "name": "Return Receipt for Merchandise" }
|
126
|
+
]
|
127
|
+
}
|
128
|
+
]
|
129
|
+
},
|
60
130
|
{
|
61
131
|
"name": "USPS 34v2",
|
62
132
|
"id": "usps_32V2",
|
@@ -131,6 +201,31 @@
|
|
131
201
|
{
|
132
202
|
"matches": "61",
|
133
203
|
"regex_group_name": "SCNC"
|
204
|
+
},
|
205
|
+
{
|
206
|
+
"regex_group_name": "ApplicationIdentifier",
|
207
|
+
"matches": "92"
|
208
|
+
}
|
209
|
+
]
|
210
|
+
}
|
211
|
+
},
|
212
|
+
{
|
213
|
+
"description": "DHL uses USPS for last mile delivery, but not all USPS91 numbers are DHL Ecommerce",
|
214
|
+
"partner_type": "shipper",
|
215
|
+
"partner_id": "dhl_ecommerce_30",
|
216
|
+
"validation": {
|
217
|
+
"matches_all": [
|
218
|
+
{
|
219
|
+
"regex_group_name": "ServiceType",
|
220
|
+
"matches": "29"
|
221
|
+
},
|
222
|
+
{
|
223
|
+
"matches": "61",
|
224
|
+
"regex_group_name": "SCNC"
|
225
|
+
},
|
226
|
+
{
|
227
|
+
"matches": "420",
|
228
|
+
"regex_group_name": "RoutingApplicationId"
|
134
229
|
}
|
135
230
|
]
|
136
231
|
}
|
data/lib/tracking_number/base.rb
CHANGED
@@ -126,16 +126,16 @@ module TrackingNumber
|
|
126
126
|
|
127
127
|
def info
|
128
128
|
Info.new({
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
129
|
+
courier: courier_info,
|
130
|
+
service_type: service_type,
|
131
|
+
service_description: service_description,
|
132
|
+
destination_zip: destination_zip,
|
133
|
+
shipper_id: shipper_id,
|
134
|
+
package_type: package_type,
|
135
|
+
tracking_url: tracking_url,
|
136
|
+
partners: partners,
|
137
|
+
decode: decode
|
138
|
+
})
|
139
139
|
end
|
140
140
|
|
141
141
|
def courier_code
|
@@ -186,8 +186,7 @@ module TrackingNumber
|
|
186
186
|
partner_hash = {}
|
187
187
|
|
188
188
|
return unless (partner_tn = find_matching_partner)
|
189
|
-
|
190
|
-
possible_twin = partner_tn.send(:find_matching_partner)
|
189
|
+
possible_twin = partner_tn.send(:find_matching_partner, self.class.const_get("ID"))
|
191
190
|
|
192
191
|
if possible_twin.instance_of?(self.class) && possible_twin.tracking_number == tracking_number
|
193
192
|
partner_hash[partner_data[:partner_type].to_sym] = partner_tn
|
@@ -235,8 +234,10 @@ module TrackingNumber
|
|
235
234
|
|
236
235
|
additional.each do |additional_info|
|
237
236
|
next unless matches && matches.length > 0 # skip if no match groups
|
237
|
+
|
238
238
|
value = matches[additional_info[:regex_group_name]].gsub(/\s/, '') # match is empty
|
239
239
|
next unless value
|
240
|
+
next unless additional_info[:lookup]
|
240
241
|
|
241
242
|
matches = additional_info[:lookup].find do |i|
|
242
243
|
if i[:matches]
|
@@ -293,8 +294,12 @@ module TrackingNumber
|
|
293
294
|
nil
|
294
295
|
end
|
295
296
|
|
296
|
-
def find_matching_partner
|
297
|
-
partner_info =
|
297
|
+
def find_matching_partner(partner_id = nil)
|
298
|
+
partner_info = if partner_id
|
299
|
+
(self.class.const_get(:PARTNERS) || []).select { |info| info[:partner_id]&.to_sym == partner_id.to_sym }
|
300
|
+
else
|
301
|
+
self.class.const_get(:PARTNERS) || []
|
302
|
+
end
|
298
303
|
|
299
304
|
partner_info.each do |partner_data|
|
300
305
|
klass = find_tracking_class_by_id(partner_data[:partner_id])
|
@@ -302,7 +307,6 @@ module TrackingNumber
|
|
302
307
|
return false unless klass
|
303
308
|
|
304
309
|
tn = klass.new(tracking_number)
|
305
|
-
|
306
310
|
valid = if partner_data.dig(:validation, :matches_all)
|
307
311
|
tn.valid? && match_all(partner_data.dig(:validation, :matches_all))
|
308
312
|
elsif partner_data.dig(:validation, :matches_any)
|
@@ -34,7 +34,13 @@ module TrackingNumber
|
|
34
34
|
|
35
35
|
def validates_mod10?(sequence, check_digit, extras = {})
|
36
36
|
total = 0
|
37
|
-
|
37
|
+
characters = if extras[:reverse]
|
38
|
+
sequence.chars.reverse
|
39
|
+
else
|
40
|
+
sequence.chars
|
41
|
+
end
|
42
|
+
|
43
|
+
characters.each_with_index do |c, i|
|
38
44
|
x = if c[/[0-9]/] # numeric
|
39
45
|
c.to_i
|
40
46
|
else
|
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: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Keen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-08-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|