omniship 0.3.2.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/omniship.rb +13 -12
- data/lib/omniship/address.rb +36 -36
- data/lib/omniship/carriers/fedex.rb +343 -188
- data/lib/omniship/carriers/ups.rb +156 -95
- data/lib/omniship/notification.rb +18 -0
- data/lib/omniship/response.rb +7 -7
- data/lib/omniship/ship_response.rb +12 -0
- data/lib/omniship/version.rb +2 -2
- data/lib/rails/generators/omniship/setup/setup_generator.rb +19 -0
- data/lib/rails/generators/omniship/setup/templates/initializer.rb +2 -0
- data/lib/rails/generators/omniship/setup/templates/omniship.yml +33 -0
- metadata +58 -73
@@ -15,7 +15,8 @@ module Omniship
|
|
15
15
|
:shipconfirm => 'ups.app/xml/ShipConfirm',
|
16
16
|
:shipaccept => 'ups.app/xml/ShipAccept',
|
17
17
|
:shipvoid => 'ups.app/xml/Void',
|
18
|
-
:valid_address => 'ups.app/xml/
|
18
|
+
:valid_address => 'ups.app/xml/AV',
|
19
|
+
:valid_address_street => 'ups.app/xml/XAV'
|
19
20
|
}
|
20
21
|
|
21
22
|
PICKUP_CODES = HashWithIndifferentAccess.new({
|
@@ -100,63 +101,71 @@ module Omniship
|
|
100
101
|
|
101
102
|
def find_rates(origin, destination, packages, options={})
|
102
103
|
origin, destination = upsified_location(origin), upsified_location(destination)
|
103
|
-
options
|
104
|
-
options[:test]
|
105
|
-
packages
|
106
|
-
access_request
|
107
|
-
rate_request
|
108
|
-
response
|
104
|
+
options = @options.merge(options)
|
105
|
+
options[:test] = options[:test].nil? ? false : options[:test]
|
106
|
+
packages = Array(packages)
|
107
|
+
access_request = build_access_request
|
108
|
+
rate_request = build_rate_request(origin, destination, packages, options)
|
109
|
+
response = commit(:rates, save_request(access_request.gsub("\n", "") + rate_request.gsub("\n", "")), options[:test])
|
109
110
|
parse_rate_response(origin, destination, packages, response, options)
|
110
111
|
end
|
111
112
|
|
112
113
|
def find_tracking_info(tracking_number, options={})
|
113
|
-
options
|
114
|
-
options[:test]
|
115
|
-
access_request
|
114
|
+
options = @options.update(options)
|
115
|
+
options[:test] = options[:test].nil? ? false : options[:test]
|
116
|
+
access_request = build_access_request
|
116
117
|
tracking_request = build_tracking_request(tracking_number, options)
|
117
|
-
response
|
118
|
-
parse_tracking_response(response, options)
|
118
|
+
response = commit(:track, save_request(access_request.gsub("\n", "") + tracking_request.gsub("\n", "")), options[:test])
|
119
|
+
# parse_tracking_response(response, options)
|
119
120
|
end
|
120
121
|
|
121
122
|
# Creating shipping functionality for UPS
|
122
123
|
def create_shipment(origin, destination, packages, options={})
|
123
|
-
@options
|
124
|
-
origin, destination
|
125
|
-
options
|
126
|
-
options[:test]
|
127
|
-
packages
|
128
|
-
access_request
|
124
|
+
@options = @options.merge(options)
|
125
|
+
origin, destination = upsified_location(origin), upsified_location(destination)
|
126
|
+
options = @options.merge(options)
|
127
|
+
options[:test] = options[:test].nil? ? true : options[:test]
|
128
|
+
packages = Array(packages)
|
129
|
+
access_request = build_access_request
|
129
130
|
ship_confirm_request = build_ship_confirm(origin, destination, packages, options)
|
130
|
-
response
|
131
|
+
response = commit(:shipconfirm, save_request(access_request.gsub("\n", "") + ship_confirm_request.gsub("\n", "")), options[:test])
|
131
132
|
parse_ship_confirm_response(origin, destination, packages, response, options)
|
132
133
|
end
|
133
134
|
|
134
135
|
def accept_shipment(digest, options={})
|
135
|
-
options[:test]
|
136
|
-
access_request
|
136
|
+
options[:test] = options[:test].nil? ? true : options[:test]
|
137
|
+
access_request = build_access_request
|
137
138
|
ship_accept_request = build_ship_accept(digest)
|
138
|
-
response
|
139
|
+
response = commit(:shipaccept, save_request(access_request.gsub("\n", "") + ship_accept_request.gsub("\n", "")), options[:test])
|
139
140
|
parse_ship_accept_response(response, options)
|
140
141
|
end
|
141
142
|
|
142
|
-
def void_shipment(ups_shipment_id,tracking_number, options={})
|
143
|
-
@options
|
144
|
-
options
|
145
|
-
options[:test]
|
146
|
-
access_request
|
143
|
+
def void_shipment(ups_shipment_id, tracking_number, options={})
|
144
|
+
@options = @options.merge(options)
|
145
|
+
options = @options.merge(options)
|
146
|
+
options[:test] = options[:test].nil? ? true : options[:test]
|
147
|
+
access_request = build_access_request
|
147
148
|
ship_void_request = build_void_request(ups_shipment_id,tracking_number)
|
148
|
-
response
|
149
|
+
response = commit(:shipvoid, save_request(access_request.gsub("\n", "") + ship_void_request.gsub("\n", "")), options[:test])
|
149
150
|
parse_ship_void_response(response, options)
|
150
151
|
end
|
151
|
-
|
152
|
-
def validate_address(
|
152
|
+
|
153
|
+
def validate_address(city, state, zip_code, country_code, options={})
|
154
|
+
@options = @options.merge(options)
|
155
|
+
access_request = build_access_request
|
156
|
+
validate_address_request = build_valid_address_request(city,state,zip_code,country_code)
|
157
|
+
options[:test] = options[:test].nil? ? true : options[:test]
|
158
|
+
response = commit(:valid_address, save_request(access_request.gsub("\n", "") + validate_address_request.gsub("\n", "")), options[:test])
|
159
|
+
parse_ship_valid_address(response)
|
160
|
+
end
|
161
|
+
|
162
|
+
def validate_address_street(address, city, state, zip_code, country_code, options={})
|
153
163
|
@options = @options.merge(options)
|
154
164
|
access_request = build_access_request
|
155
|
-
|
165
|
+
validate_address_street_request = build_valid_address_street_request(address,city,state,zip_code,country_code)
|
156
166
|
options[:test] = options[:test].nil? ? true : options[:test]
|
157
|
-
response = commit(:
|
158
|
-
|
159
|
-
parse_response
|
167
|
+
response = commit(:valid_address_street, save_request(access_request.gsub("\n", "") + validate_address_street_request.gsub("\n", "")), options[:test])
|
168
|
+
parse_ship_valid_address_street(response)
|
160
169
|
end
|
161
170
|
|
162
171
|
protected
|
@@ -172,7 +181,7 @@ module Omniship
|
|
172
181
|
location
|
173
182
|
end
|
174
183
|
end
|
175
|
-
|
184
|
+
|
176
185
|
|
177
186
|
def build_access_request
|
178
187
|
builder = Nokogiri::XML::Builder.new do |xml|
|
@@ -180,17 +189,12 @@ module Omniship
|
|
180
189
|
xml.AccessLicenseNumber @options[:key].nil? ? @config['ups']['key'] : @options[:key]
|
181
190
|
xml.UserId @options[:login].nil? ? @config['ups']['username'] : @options[:login]
|
182
191
|
xml.Password @options[:password].nil? ? @config['ups']['password'] : @options[:password]
|
183
|
-
|
184
|
-
|
185
|
-
xml.AccessLicenseNumber @config['ups']['key'] unless @options[:key]
|
186
|
-
xml.UserId @config['ups']['username'] unless @options[:login]
|
187
|
-
xml.Password @config['ups']['password'] unless @options[:password]
|
188
192
|
}
|
189
193
|
end
|
190
194
|
builder.to_xml
|
191
195
|
end
|
192
196
|
|
193
|
-
# Build the ship_confirm XML request
|
197
|
+
# Build the ship_confirm XML request
|
194
198
|
def build_ship_confirm(origin, destination, packages, options={})
|
195
199
|
|
196
200
|
#Return Service types:
|
@@ -206,7 +210,7 @@ module Omniship
|
|
206
210
|
xml.ShipmentConfirmRequest {
|
207
211
|
xml.Request {
|
208
212
|
xml.RequestAction 'ShipConfirm'
|
209
|
-
xml.RequestOption 'validate'
|
213
|
+
xml.RequestOption options[:nonvalidate] ? 'nonvalidate' : 'validate'
|
210
214
|
}
|
211
215
|
xml.Shipment {
|
212
216
|
build_location_node(['Shipper'], (options[:shipper] || origin), options, xml)
|
@@ -270,6 +274,17 @@ module Omniship
|
|
270
274
|
}
|
271
275
|
end
|
272
276
|
}
|
277
|
+
if package.options[:references].present?
|
278
|
+
package.options[:references].each do |reference|
|
279
|
+
xml.ReferenceNumber {
|
280
|
+
xml.Code reference[:code]
|
281
|
+
xml.Value reference[:value]
|
282
|
+
if reference[:barcode]
|
283
|
+
xml.BarCodeIndicator
|
284
|
+
end
|
285
|
+
}
|
286
|
+
end
|
287
|
+
end
|
273
288
|
}
|
274
289
|
end
|
275
290
|
xml.LabelSpecification {
|
@@ -312,23 +327,40 @@ module Omniship
|
|
312
327
|
end
|
313
328
|
builder.to_xml
|
314
329
|
end
|
315
|
-
|
316
|
-
def
|
330
|
+
|
331
|
+
def build_valid_address_street_request(address,city,state,zip_code,country_code)
|
317
332
|
builder = Nokogiri::XML::Builder.new do |xml|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
xml.
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
333
|
+
xml.AddressValidationRequest {
|
334
|
+
xml.Request {
|
335
|
+
xml.RequestAction "XAV"
|
336
|
+
}
|
337
|
+
|
338
|
+
xml.AddressKeyFormat {
|
339
|
+
xml.AddressLine address
|
340
|
+
xml.PoliticalDivision2 city
|
341
|
+
xml.PoliticalDivision1 state
|
342
|
+
xml.PostcodePrimaryLow zip_code
|
343
|
+
xml.CountryCode country_code
|
344
|
+
}
|
345
|
+
}
|
346
|
+
end
|
347
|
+
builder.to_xml
|
348
|
+
end
|
349
|
+
|
350
|
+
def build_valid_address_request(city,state,zip_code,country_code)
|
351
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
352
|
+
xml.AddressValidationRequest {
|
353
|
+
xml.Request{
|
354
|
+
xml.RequestAction 'AV'
|
355
|
+
}
|
356
|
+
|
357
|
+
xml.Address{
|
358
|
+
xml.City city
|
359
|
+
xml.StateProvinceCode state
|
360
|
+
xml.CountryCode country_code
|
361
|
+
xml.PostalCode zip_code
|
331
362
|
}
|
363
|
+
}
|
332
364
|
end
|
333
365
|
builder.to_xml
|
334
366
|
end
|
@@ -414,11 +446,14 @@ module Omniship
|
|
414
446
|
builder = Nokogiri::XML::Builder.new do |xml|
|
415
447
|
xml.TrackRequest {
|
416
448
|
xml.Request {
|
417
|
-
xml.
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
xml.
|
449
|
+
xml.TransactionReference {
|
450
|
+
}
|
451
|
+
xml.RequestAction "Track"
|
452
|
+
}
|
453
|
+
xml.TrackingNumber tracking_number.to_s
|
454
|
+
xml.ShipmentType {
|
455
|
+
xml.Code "01"
|
456
|
+
}
|
422
457
|
}
|
423
458
|
end
|
424
459
|
builder.to_xml
|
@@ -480,47 +515,47 @@ module Omniship
|
|
480
515
|
RateResponse.new(success, message, Hash.from_xml(response).values.first, :rates => rate_estimates, :xml => response, :request => last_request)
|
481
516
|
end
|
482
517
|
|
483
|
-
def parse_tracking_response(response, options={})
|
518
|
+
def parse_tracking_response(response, options={})
|
484
519
|
xml = Nokogiri::XML(response)
|
485
520
|
success = response_success?(xml)
|
486
521
|
message = response_message(xml)
|
487
|
-
|
522
|
+
|
488
523
|
puts "response :" + xml.to_s
|
489
|
-
|
524
|
+
|
490
525
|
if success
|
491
526
|
tracking_number, origin, destination = nil
|
492
527
|
shipment_details = Hash.new
|
493
|
-
|
494
|
-
tracking_number = xml.xpath('/*/Shipment/Package/TrackingNumber').text
|
528
|
+
|
529
|
+
tracking_number = xml.xpath('/*/Shipment/Package/TrackingNumber').text
|
495
530
|
shipment_details[:tracking_number] = tracking_number
|
496
|
-
|
497
|
-
estimated_delivery_date = xml.xpath('/*/Shipment/ScheduledDeliveryDate').text
|
498
|
-
if !estimated_delivery_date.blank?
|
531
|
+
|
532
|
+
estimated_delivery_date = xml.xpath('/*/Shipment/ScheduledDeliveryDate').text
|
533
|
+
if !estimated_delivery_date.blank?
|
499
534
|
estimated_delivery_date = Date.strptime(estimated_delivery_date,'%Y%m%d')
|
500
535
|
shipment_details[:estimated_delivery_date] = estimated_delivery_date
|
501
536
|
else
|
502
|
-
reschedule_delivery_date = xml.xpath('/*/Shipment/Package/RescheduledDeliveryDate').text
|
503
|
-
if !reschedule_delivery_date.blank?
|
537
|
+
reschedule_delivery_date = xml.xpath('/*/Shipment/Package/RescheduledDeliveryDate').text
|
538
|
+
if !reschedule_delivery_date.blank?
|
504
539
|
reschedule_delivery_date = Date.strptime(reschedule_delivery_date,'%Y%m%d')
|
505
540
|
shipment_details[:estimated_delivery_date] = reschedule_delivery_date
|
506
541
|
end
|
507
542
|
end
|
508
|
-
|
543
|
+
|
509
544
|
puts 'tracking_number: ' + tracking_number
|
510
|
-
puts 'estimated_delivery_date: ' + estimated_delivery_date.to_s
|
511
|
-
|
545
|
+
puts 'estimated_delivery_date: ' + estimated_delivery_date.to_s
|
546
|
+
|
512
547
|
activities = []
|
513
548
|
xml.xpath('/*/Shipment/Package/Activity').each do |activity|
|
514
|
-
status_code = activity.xpath('Status/StatusCode').text
|
515
|
-
status_dsc = activity.xpath('Status/StatusType/Description').text
|
516
|
-
date = activity.xpath('Date').text
|
517
|
-
time = activity.xpath('Time').text
|
549
|
+
status_code = activity.xpath('Status/StatusCode').text
|
550
|
+
status_dsc = activity.xpath('Status/StatusType/Description').text
|
551
|
+
date = activity.xpath('Date').text
|
552
|
+
time = activity.xpath('Time').text
|
518
553
|
hour, minute, second = time.scan(/\d{2}/)
|
519
554
|
year, month, day = date[0..3], date[4..5], date[6..7]
|
520
|
-
date_time = Time.utc(year, month, day, hour, minute, second)
|
521
|
-
location = activity.xpath('ActivityLocation/Address/City').text + ' ' + activity.xpath('ActivityLocation/Address/StateProvinceCode').text + ' ' + activity.xpath('ActivityLocation/Address/CountryCode').text
|
555
|
+
date_time = Time.utc(year, month, day, hour, minute, second)
|
556
|
+
location = activity.xpath('ActivityLocation/Address/City').text + ' ' + activity.xpath('ActivityLocation/Address/StateProvinceCode').text + ' ' + activity.xpath('ActivityLocation/Address/CountryCode').text
|
522
557
|
activities << {:status_code => status_code, :status_dsc => status_dsc, :date => date_time, :location => location}
|
523
|
-
end
|
558
|
+
end
|
524
559
|
shipment_details[:activities] = activities
|
525
560
|
|
526
561
|
#first_shipment = xml.gelements['/*/Shipment']
|
@@ -545,9 +580,9 @@ module Omniship
|
|
545
580
|
# location = location_from_address_node(activity.elements['ActivityLocation/Address'])
|
546
581
|
# ShipmentEvent.new(description, zoneless_time, location)
|
547
582
|
# end
|
548
|
-
#
|
583
|
+
#
|
549
584
|
# shipment_events = shipment_events.sort_by(&:time)
|
550
|
-
#
|
585
|
+
#
|
551
586
|
# if origin
|
552
587
|
# first_event = shipment_events[0]
|
553
588
|
# same_country = origin.country_code(:alpha2) == first_event.location.country_code(:alpha2)
|
@@ -633,26 +668,52 @@ module Omniship
|
|
633
668
|
|
634
669
|
return @void
|
635
670
|
end
|
636
|
-
|
671
|
+
|
637
672
|
def parse_ship_valid_address(response, options={})
|
638
673
|
xml = Nokogiri::XML(response)
|
674
|
+
puts xml
|
639
675
|
success = response_success?(xml)
|
640
|
-
|
676
|
+
response_text = Array.new
|
641
677
|
if success
|
642
|
-
addresses = xml.xpath('/*/
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
678
|
+
addresses = xml.xpath('/*/AddressValidationResult').each do |address_data|
|
679
|
+
response_text = Hash.new
|
680
|
+
response_text[:rank] = address_data.xpath('Rank').text
|
681
|
+
response_text[:quality] = address_data.xpath('Quality').text
|
682
|
+
response_text[:city] = address_data.xpath('Address/City').text
|
683
|
+
response_text[:state] = address_data.xpath('Address/StateProvinceCode').text
|
684
|
+
response_text[:postal_code_low] = address_data.xpath('PostalCodeLowEnd').text
|
685
|
+
response_text[:postal_code_high] = address_data.xpath('PostalCodeHighEnd').text
|
650
686
|
end
|
651
687
|
else
|
652
688
|
return "Address validation failed!"
|
653
689
|
end
|
690
|
+
return response_text
|
691
|
+
end
|
654
692
|
|
655
|
-
|
693
|
+
def parse_ship_valid_address_street(response, options={})
|
694
|
+
n = 1
|
695
|
+
xml = Nokogiri::XML(response)
|
696
|
+
puts xml
|
697
|
+
success = response_success?(xml)
|
698
|
+
response_text = Array.new
|
699
|
+
if success
|
700
|
+
addresses = xml.xpath('/*/AddressKeyFormat').each do |address_data|
|
701
|
+
response_text = Hash.new
|
702
|
+
address_data.xpath('AddressLine').each do |address_line|
|
703
|
+
response_text["address_#{n}".to_sym] = address_line.text
|
704
|
+
n += 1
|
705
|
+
end
|
706
|
+
response_text[:region] = address_data.xpath('Region').text
|
707
|
+
response_text[:city] = address_data.xpath('PoliticalDivision2').text
|
708
|
+
response_text[:state] = address_data.xpath('PoliticalDivision1').text
|
709
|
+
response_text[:postal_code] = address_data.xpath('PostcodePrimaryLow').text
|
710
|
+
response_text[:postal_code_extended] = address_data.xpath('PostcodeExtendedLow').text
|
711
|
+
response_text[:country_code] = address_data.xpath("CountryCode").text
|
712
|
+
end
|
713
|
+
else
|
714
|
+
return "Address validation failed!"
|
715
|
+
end
|
716
|
+
return response_text
|
656
717
|
end
|
657
718
|
|
658
719
|
def location_from_address_node(address)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Omniship #:nodoc:
|
2
|
+
class Notification
|
3
|
+
attr_reader :options
|
4
|
+
attr_reader :email
|
5
|
+
attr_reader :format
|
6
|
+
attr_reader :language
|
7
|
+
attr_reader :locale_code
|
8
|
+
|
9
|
+
alias_method :email_address, :email
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@email = options[:email]
|
13
|
+
@format = options[:format]
|
14
|
+
@language = options[:language]
|
15
|
+
@locale_code = options[:locale_code]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/omniship/response.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module Omniship #:nodoc:
|
2
2
|
class Error < StandardError
|
3
3
|
end
|
4
|
-
|
4
|
+
|
5
5
|
class ResponseError < Error
|
6
6
|
attr_reader :response
|
7
|
-
|
7
|
+
|
8
8
|
def initialize(response = nil)
|
9
9
|
if response.is_a? Response
|
10
10
|
super(response.message)
|
@@ -12,17 +12,17 @@ module Omniship #:nodoc:
|
|
12
12
|
else
|
13
13
|
super(response)
|
14
14
|
end
|
15
|
-
end
|
15
|
+
end
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
class Response
|
19
|
-
|
19
|
+
|
20
20
|
attr_reader :params
|
21
21
|
attr_reader :message
|
22
22
|
attr_reader :test
|
23
23
|
attr_reader :xml
|
24
24
|
attr_reader :request
|
25
|
-
|
25
|
+
|
26
26
|
def initialize(success, message, params = {}, options = {})
|
27
27
|
@success, @message, @params = success, message, params.stringify_keys
|
28
28
|
@test = options[:test] || false
|
@@ -30,7 +30,7 @@ module Omniship #:nodoc:
|
|
30
30
|
@request = options[:request]
|
31
31
|
raise ResponseError.new(self) unless success
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
def success?
|
35
35
|
@success ? true : false
|
36
36
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Omniship #:nodoc:
|
2
|
+
class ShipResponse < Response
|
3
|
+
attr_reader :tracking_number
|
4
|
+
attr_reader :label_encoded
|
5
|
+
|
6
|
+
def initialize(success, message, params = {}, options = {})
|
7
|
+
@tracking_number = params[:tracking_number]
|
8
|
+
@label_encoded = params[:label_encoded]
|
9
|
+
super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|