spree_active_shipping 1.0.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.
- data/.gitignore +2 -0
- data/README.md +67 -0
- data/Rakefile +45 -0
- data/app/controllers/admin/shipments_controller_decorator.rb +11 -0
- data/app/controllers/admin/shipping_methods_controller_decorator.rb +15 -0
- data/app/controllers/checkout_controller_decorator.rb +11 -0
- data/app/models/calculator/active_shipping.rb +126 -0
- data/app/models/calculator/fedex/base.rb +8 -0
- data/app/models/calculator/fedex/base.rb~ +7 -0
- data/app/models/calculator/fedex/express_saver.rb +5 -0
- data/app/models/calculator/fedex/first_overnight.rb +5 -0
- data/app/models/calculator/fedex/ground.rb +5 -0
- data/app/models/calculator/fedex/ground_home_delivery.rb +5 -0
- data/app/models/calculator/fedex/international_economy.rb +5 -0
- data/app/models/calculator/fedex/international_economy_freight.rb +5 -0
- data/app/models/calculator/fedex/international_first.rb +5 -0
- data/app/models/calculator/fedex/international_ground.rb +5 -0
- data/app/models/calculator/fedex/international_priority.rb +5 -0
- data/app/models/calculator/fedex/international_priority_freight.rb +5 -0
- data/app/models/calculator/fedex/international_priority_saturday_delivery.rb +5 -0
- data/app/models/calculator/fedex/one_day_freight.rb +5 -0
- data/app/models/calculator/fedex/one_day_freight_saturday_delivery.rb +5 -0
- data/app/models/calculator/fedex/priority_overnight.rb +5 -0
- data/app/models/calculator/fedex/priority_overnight_saturday_delivery.rb +5 -0
- data/app/models/calculator/fedex/saver.rb +5 -0
- data/app/models/calculator/fedex/saver.rb~ +5 -0
- data/app/models/calculator/fedex/standard_overnight.rb +5 -0
- data/app/models/calculator/fedex/three_day_freight.rb +5 -0
- data/app/models/calculator/fedex/three_day_freight_saturday_delivery.rb +5 -0
- data/app/models/calculator/fedex/two_day.rb +5 -0
- data/app/models/calculator/fedex/two_day_freight.rb +5 -0
- data/app/models/calculator/fedex/two_day_freight_saturday_delivery.rb +5 -0
- data/app/models/calculator/fedex/two_day_saturday_delivery.rb +5 -0
- data/app/models/calculator/ups/base.rb +15 -0
- data/app/models/calculator/ups/ground.rb +5 -0
- data/app/models/calculator/ups/next_day_air.rb +5 -0
- data/app/models/calculator/ups/next_day_air_early_am.rb +5 -0
- data/app/models/calculator/ups/next_day_air_saver.rb +5 -0
- data/app/models/calculator/ups/saver.rb +5 -0
- data/app/models/calculator/ups/second_day_air.rb +5 -0
- data/app/models/calculator/ups/three_day_select.rb +5 -0
- data/app/models/calculator/ups/worldwide_expedited.rb +5 -0
- data/app/models/calculator/usps/base.rb +5 -0
- data/app/models/calculator/usps/express_mail.rb +5 -0
- data/app/models/calculator/usps/express_mail_international.rb +5 -0
- data/app/models/calculator/usps/media_mail.rb +5 -0
- data/app/models/calculator/usps/priority_mail.rb +5 -0
- data/app/models/calculator/usps/priority_mail_international.rb +5 -0
- data/app/models/calculator/usps/priority_mail_large_flat_rate_box.rb +5 -0
- data/app/models/calculator/usps/priority_mail_regular_medium_flat_rate_boxes.rb +5 -0
- data/app/models/calculator/usps/priority_mail_small_flat_rate_box.rb +5 -0
- data/app/views/admin/shipping_methods/_form.html.erb +42 -0
- data/config/locales/en.yml +3 -0
- data/lib/active_shipping_configuration.rb +25 -0
- data/lib/spree/active_shipping/config.rb +22 -0
- data/lib/spree/active_shipping/ups_override.rb +274 -0
- data/lib/spree/shipping_error.rb +3 -0
- data/lib/spree_active_shipping.rb +74 -0
- data/lib/tasks/active_shipping_extension_tasks.rake +29 -0
- data/spec/lib/spree/bogus_calculator.rb +11 -0
- data/spec/lib/spree/bogus_carrier.rb +15 -0
- data/spec/models/active_shipping_calculator_spec.rb +51 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +33 -0
- data/spree_active_shipping.gemspec +23 -0
- metadata +184 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
class Calculator::Ups::Base < Calculator::ActiveShipping
|
2
|
+
def carrier
|
3
|
+
if Spree::ActiveShipping::Config[:shipper_number].nil?
|
4
|
+
ActiveMerchant::Shipping::UPS.new(:login => Spree::ActiveShipping::Config[:ups_login],
|
5
|
+
:password => Spree::ActiveShipping::Config[:ups_password],
|
6
|
+
:key => Spree::ActiveShipping::Config[:ups_key])
|
7
|
+
else
|
8
|
+
ActiveMerchant::Shipping::UPS.new(:login => Spree::ActiveShipping::Config[:ups_login],
|
9
|
+
:password => Spree::ActiveShipping::Config[:ups_password],
|
10
|
+
:key => Spree::ActiveShipping::Config[:ups_key],
|
11
|
+
:origin_account => Spree::ActiveShipping::Config[:shipper_number])
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<%- locals = {:f => f} %>
|
2
|
+
<%= hook :admin_shipping_method_form_fields, locals do %>
|
3
|
+
<%= f.field_container :name do %>
|
4
|
+
<%= f.label :name, t("name") %><br />
|
5
|
+
<%= f.text_field :name %>
|
6
|
+
<%= error_message_on :shipping_method, :name %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<%= f.field_container :zone_id do %>
|
10
|
+
<%= f.label :zone_id, t("zone") %><br />
|
11
|
+
<%= f.collection_select(:zone_id, @available_zones, :id, :name, {}, {"style" => "width:200px"}) %>
|
12
|
+
<%= error_message_on :shipping_method, :zone_id %>
|
13
|
+
<% end %>
|
14
|
+
<%= f.field_container :display_on do %>
|
15
|
+
<%= f.label :display_on, t("display") %><br />
|
16
|
+
<%= select(:shipping_method, :display_on, ShippingMethod::DISPLAY.collect {|display| [t(display), display == :both ? nil : display.to_s]}) %>
|
17
|
+
<%= error_message_on :shipping_method, :display_on %>
|
18
|
+
<% end %>
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
<%= hook :admin_shipping_method_form_calculator_fields, locals do %>
|
22
|
+
<fieldset id="calculator_fields">
|
23
|
+
<legend><%= t('calculator') %></legend>
|
24
|
+
<div id="preference-settings">
|
25
|
+
<p>
|
26
|
+
<%= f.label(:calc_type, t("calculator")) %>
|
27
|
+
<%= f.collection_select(:calculator_type, @calculators, :class, :description, {}, {:id => "calc-type"}) %>
|
28
|
+
</p>
|
29
|
+
<% if !@object.new_record? %>
|
30
|
+
<div class="calculator-settings">
|
31
|
+
<%= f.fields_for :calculator do |calculator_form| %>
|
32
|
+
<%= preference_fields(@object.calculator, calculator_form) %>
|
33
|
+
<% end %>
|
34
|
+
</div>
|
35
|
+
<% if @object.calculator.respond_to?(:preferences) %>
|
36
|
+
<div id="calculator-settings-warning"><%= t('calculator_settings_warning')%></div>
|
37
|
+
<% end %>
|
38
|
+
<% end %>
|
39
|
+
</div>
|
40
|
+
</fieldset>
|
41
|
+
<% end %>
|
42
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class ActiveShippingConfiguration < Configuration
|
2
|
+
|
3
|
+
preference :ups_login, :string, :default => "aunt_judy"
|
4
|
+
preference :ups_password, :string, :default => "secret"
|
5
|
+
preference :ups_key, :string, :default => "developer_key"
|
6
|
+
preference :shipper_number, :string, :default => nil
|
7
|
+
|
8
|
+
preference :fedex_login, :string, :default => "meter_no"
|
9
|
+
preference :fedex_password, :string, :default => "special_sha1_looking_thing_sent_via_email"
|
10
|
+
preference :fedex_account, :string, :default => "account_no"
|
11
|
+
preference :fedex_key, :string, :default => "authorization_key"
|
12
|
+
|
13
|
+
preference :usps_login, :string, :default => "aunt_judy"
|
14
|
+
|
15
|
+
preference :origin_country, :string, :default => "US"
|
16
|
+
preference :origin_state, :string, :default => "PA"
|
17
|
+
preference :origin_city, :string, :default => "University Park"
|
18
|
+
preference :origin_zip, :string, :default => "16802"
|
19
|
+
|
20
|
+
preference :units, :string, :default => "imperial"
|
21
|
+
preference :unit_multiplier, :integer, :default => 16 # 16 oz./lb - assumes variant weights are in lbs
|
22
|
+
|
23
|
+
validates_presence_of :name
|
24
|
+
validates_uniqueness_of :name
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Spree
|
2
|
+
module ActiveShipping
|
3
|
+
# Singleton class to access the shipping configuration object (ActiveShippingConfiguration.first by default) and it's preferences.
|
4
|
+
#
|
5
|
+
# Usage:
|
6
|
+
# Spree::ActiveShipping::Config[:foo] # Returns the foo preference
|
7
|
+
# Spree::ActiveShipping::Config[] # Returns a Hash with all the tax preferences
|
8
|
+
# Spree::ActiveShipping::Config.instance # Returns the configuration object (ActiveShippingConfiguration.first)
|
9
|
+
# Spree::ActiveShipping::Config.set(preferences_hash) # Set the active shipping preferences as especified in +preference_hash+
|
10
|
+
class Config
|
11
|
+
include Singleton
|
12
|
+
include PreferenceAccess
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def instance
|
16
|
+
return nil unless ActiveRecord::Base.connection.tables.include?('configurations')
|
17
|
+
ActiveShippingConfiguration.find_or_create_by_name("Default active_shipping configuration")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,274 @@
|
|
1
|
+
module Spree
|
2
|
+
module ActiveShipping
|
3
|
+
module UpsOverride
|
4
|
+
def self.included(base)
|
5
|
+
|
6
|
+
base.class_eval do
|
7
|
+
|
8
|
+
def build_rate_request(origin, destination, packages, options={})
|
9
|
+
packages = Array(packages)
|
10
|
+
xml_request = XmlNode.new('RatingServiceSelectionRequest') do |root_node|
|
11
|
+
root_node << XmlNode.new('Request') do |request|
|
12
|
+
request << XmlNode.new('RequestAction', 'Rate')
|
13
|
+
request << XmlNode.new('RequestOption', 'Shop')
|
14
|
+
# not implemented: 'Rate' RequestOption to specify a single service query
|
15
|
+
# request << XmlNode.new('RequestOption', ((options[:service].nil? or options[:service] == :all) ? 'Shop' : 'Rate'))
|
16
|
+
end
|
17
|
+
|
18
|
+
pickup_type = options[:pickup_type] || :daily_pickup
|
19
|
+
|
20
|
+
root_node << XmlNode.new('PickupType') do |pickup_type_node|
|
21
|
+
pickup_type_node << XmlNode.new('Code', ActiveMerchant::Shipping::UPS::PICKUP_CODES[pickup_type])
|
22
|
+
# not implemented: PickupType/PickupDetails element
|
23
|
+
end
|
24
|
+
cc = options[:customer_classification] || ActiveMerchant::Shipping::UPS::DEFAULT_CUSTOMER_CLASSIFICATIONS[pickup_type]
|
25
|
+
root_node << XmlNode.new('CustomerClassification') do |cc_node|
|
26
|
+
cc_node << XmlNode.new('Code', ActiveMerchant::Shipping::UPS::CUSTOMER_CLASSIFICATIONS[cc])
|
27
|
+
end
|
28
|
+
|
29
|
+
root_node << XmlNode.new('Shipment') do |shipment|
|
30
|
+
# not implemented: Shipment/Description element
|
31
|
+
shipment << build_location_node('Shipper', (options[:shipper] || origin), options)
|
32
|
+
shipment << build_location_node('ShipTo', destination, options)
|
33
|
+
if options[:shipper] and options[:shipper] != origin
|
34
|
+
shipment << build_location_node('ShipFrom', origin, options)
|
35
|
+
end
|
36
|
+
|
37
|
+
# not implemented: * Shipment/ShipmentWeight element
|
38
|
+
# * Shipment/ReferenceNumber element
|
39
|
+
# * Shipment/Service element
|
40
|
+
# * Shipment/PickupDate element
|
41
|
+
# * Shipment/ScheduledDeliveryDate element
|
42
|
+
# * Shipment/ScheduledDeliveryTime element
|
43
|
+
# * Shipment/AlternateDeliveryTime element
|
44
|
+
# * Shipment/DocumentsOnly element
|
45
|
+
|
46
|
+
packages.each do |package|
|
47
|
+
|
48
|
+
|
49
|
+
imperial = ['US','LR','MM'].include?(origin.country_code(:alpha2))
|
50
|
+
|
51
|
+
shipment << XmlNode.new("Package") do |package_node|
|
52
|
+
|
53
|
+
# not implemented: * Shipment/Package/PackagingType element
|
54
|
+
# * Shipment/Package/Description element
|
55
|
+
|
56
|
+
package_node << XmlNode.new("PackagingType") do |packaging_type|
|
57
|
+
packaging_type << XmlNode.new("Code", '02')
|
58
|
+
end
|
59
|
+
|
60
|
+
package_node << XmlNode.new("Dimensions") do |dimensions|
|
61
|
+
dimensions << XmlNode.new("UnitOfMeasurement") do |units|
|
62
|
+
units << XmlNode.new("Code", imperial ? 'IN' : 'CM')
|
63
|
+
end
|
64
|
+
[:length,:width,:height].each do |axis|
|
65
|
+
value = ((imperial ? package.inches(axis) : package.cm(axis)).to_f*1000).round/1000.0 # 3 decimals
|
66
|
+
dimensions << XmlNode.new(axis.to_s.capitalize, [value,0.1].max)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
package_node << XmlNode.new("PackageWeight") do |package_weight|
|
71
|
+
package_weight << XmlNode.new("UnitOfMeasurement") do |units|
|
72
|
+
units << XmlNode.new("Code", imperial ? 'LBS' : 'KGS')
|
73
|
+
end
|
74
|
+
|
75
|
+
value = ((imperial ? package.lbs : package.kgs).to_f*1000).round/1000.0 # 3 decimals
|
76
|
+
package_weight << XmlNode.new("Weight", [value,0.1].max)
|
77
|
+
end
|
78
|
+
|
79
|
+
# not implemented: * Shipment/Package/LargePackageIndicator element
|
80
|
+
# * Shipment/Package/ReferenceNumber element
|
81
|
+
# * Shipment/Package/PackageServiceOptions element
|
82
|
+
# * Shipment/Package/AdditionalHandling element
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
# not implemented: * Shipment/ShipmentServiceOptions element
|
88
|
+
# * Shipment/RateInformation element
|
89
|
+
|
90
|
+
#SPREE OVERRIDE Negotiated Rates
|
91
|
+
if (origin_account = @options[:origin_account] || options[:origin_account])
|
92
|
+
shipment << XmlNode.new("RateInformation") do |rate_information|
|
93
|
+
rate_information << XmlNode.new("NegotiatedRatesIndicator", '')
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
xml_request.to_s
|
100
|
+
end
|
101
|
+
|
102
|
+
def build_time_in_transit_request(origin, destination, packages, options={})
|
103
|
+
packages = Array(packages)
|
104
|
+
xml_request = XmlNode.new('TimeInTransitRequest') do |root_node|
|
105
|
+
root_node << XmlNode.new('Request') do |request|
|
106
|
+
request << XmlNode.new('TransactionReference') do |transaction_reference|
|
107
|
+
transaction_reference << XmlNode.new('CustomerContext', 'Time in Transit')
|
108
|
+
transaction_reference << XmlNode.new('XpciVersion', '1.0002')
|
109
|
+
end
|
110
|
+
request << XmlNode.new('RequestAction', 'TimeInTransit')
|
111
|
+
end
|
112
|
+
root_node << XmlNode.new('TransitFrom') do |transit_from|
|
113
|
+
transit_from << XmlNode.new('AddressArtifactFormat') do |address_artifact_format|
|
114
|
+
address_artifact_format << XmlNode.new('PoliticalDivision2',origin.city)
|
115
|
+
address_artifact_format << XmlNode.new('PoliticalDivision1',origin.state)
|
116
|
+
address_artifact_format << XmlNode.new('CountryCode',origin.country_code(:alpha2))
|
117
|
+
address_artifact_format << XmlNode.new('PostcodePrimaryLow',origin.postal_code)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
root_node << XmlNode.new('TransitTo') do |transit_to|
|
122
|
+
transit_to << XmlNode.new('AddressArtifactFormat') do |address_artifact_format|
|
123
|
+
address_artifact_format << XmlNode.new('PoliticalDivision2',destination.city)
|
124
|
+
address_artifact_format << XmlNode.new('PoliticalDivision1',destination.state)
|
125
|
+
address_artifact_format << XmlNode.new('CountryCode',destination.country_code(:alpha2))
|
126
|
+
address_artifact_format << XmlNode.new('PostcodePrimaryLow',destination.postal_code)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
root_node << XmlNode.new("ShipmentWeight") do |shipment_weight|
|
131
|
+
shipment_weight << XmlNode.new("UnitOfMeasurement") do |units|
|
132
|
+
units << XmlNode.new("Code", 'LBS')
|
133
|
+
end
|
134
|
+
|
135
|
+
value = ((packages[0].lbs).to_f*1000).round/1000.0 # 3 decimals
|
136
|
+
shipment_weight << XmlNode.new("Weight", [value,0.1].max)
|
137
|
+
end
|
138
|
+
|
139
|
+
root_node << XmlNode.new("InvoiceLineTotal") do |invoice_line_total|
|
140
|
+
invoice_line_total << XmlNode.new("CurrencyCode","USD")
|
141
|
+
invoice_line_total << XmlNode.new("MonetaryValue","50")
|
142
|
+
end
|
143
|
+
|
144
|
+
root_node << XmlNode.new("PickupDate",Date.today.strftime("%Y%m%d"))
|
145
|
+
|
146
|
+
|
147
|
+
end
|
148
|
+
xml_request.to_s
|
149
|
+
end
|
150
|
+
|
151
|
+
def build_location_node(name,location,options={})
|
152
|
+
# not implemented: * Shipment/Shipper/Name element
|
153
|
+
# * Shipment/(ShipTo|ShipFrom)/CompanyName element
|
154
|
+
# * Shipment/(Shipper|ShipTo|ShipFrom)/AttentionName element
|
155
|
+
# * Shipment/(Shipper|ShipTo|ShipFrom)/TaxIdentificationNumber element
|
156
|
+
location_node = XmlNode.new(name) do |location_node|
|
157
|
+
location_node << XmlNode.new('PhoneNumber', location.phone.gsub(/[^\d]/,'')) unless location.phone.blank?
|
158
|
+
location_node << XmlNode.new('FaxNumber', location.fax.gsub(/[^\d]/,'')) unless location.fax.blank?
|
159
|
+
|
160
|
+
if name == 'Shipper' and (origin_account = @options[:origin_account] || options[:origin_account])
|
161
|
+
location_node << XmlNode.new('ShipperNumber', origin_account)
|
162
|
+
elsif name == 'ShipTo' and (destination_account = @options[:destination_account] || options[:destination_account])
|
163
|
+
location_node << XmlNode.new('ShipperAssignedIdentificationNumber', destination_account)
|
164
|
+
end
|
165
|
+
|
166
|
+
location_node << XmlNode.new('Address') do |address|
|
167
|
+
address << XmlNode.new("AddressLine1", location.address1) unless location.address1.blank?
|
168
|
+
address << XmlNode.new("AddressLine2", location.address2) unless location.address2.blank?
|
169
|
+
address << XmlNode.new("AddressLine3", location.address3) unless location.address3.blank?
|
170
|
+
address << XmlNode.new("City", location.city) unless location.city.blank?
|
171
|
+
address << XmlNode.new("StateProvinceCode", location.state) unless location.state.blank? #SPREE OVERRIDE
|
172
|
+
# StateProvinceCode required for negotiated rates but not otherwise, for some reason
|
173
|
+
address << XmlNode.new("PostalCode", location.postal_code) unless location.postal_code.blank?
|
174
|
+
address << XmlNode.new("CountryCode", location.country_code(:alpha2)) unless location.country_code(:alpha2).blank?
|
175
|
+
address << XmlNode.new("ResidentialAddressIndicator", true) unless location.commercial? # the default should be that UPS returns residential rates for destinations that it doesn't know about
|
176
|
+
# not implemented: Shipment/(Shipper|ShipTo|ShipFrom)/Address/ResidentialAddressIndicator element
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def find_time_in_transit(origin, destination, packages, options={})
|
182
|
+
origin, destination = upsified_location(origin), upsified_location(destination)
|
183
|
+
options = @options.merge(options)
|
184
|
+
packages = Array(packages)
|
185
|
+
access_request = build_access_request
|
186
|
+
rate_request = build_time_in_transit_request(origin, destination, packages, options)
|
187
|
+
response = ssl_post("https://www.ups.com/ups.app/xml/TimeInTransit", "<?xml version=\"1.0\"?>"+access_request+"<?xml version=\"1.0\"?>"+rate_request)
|
188
|
+
parse_time_in_transit_response(origin, destination, packages,response, options)
|
189
|
+
end
|
190
|
+
|
191
|
+
def find_rates(origin, destination, packages, options={})
|
192
|
+
origin, destination = upsified_location(origin), upsified_location(destination)
|
193
|
+
options = @options.merge(options)
|
194
|
+
packages = Array(packages)
|
195
|
+
access_request = build_access_request
|
196
|
+
rate_request = build_rate_request(origin, destination, packages, options)
|
197
|
+
response = commit(:rates, save_request(access_request + rate_request), (options[:test] || false))
|
198
|
+
parse_rate_response(origin, destination, packages, response, options)
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
def parse_time_in_transit_response(origin, destination, packages, response, options={})
|
203
|
+
|
204
|
+
time_code_mapping = {
|
205
|
+
"1DA" => "01",
|
206
|
+
"2DA" => "02",
|
207
|
+
"GND" => "03",
|
208
|
+
"01" => "07",
|
209
|
+
"05" => "08",
|
210
|
+
"03" => "11",
|
211
|
+
"3DS" => "12",
|
212
|
+
"1DP" => "13",
|
213
|
+
"1DM" => "14",
|
214
|
+
"21" => "54",
|
215
|
+
"2DM" => "59"
|
216
|
+
}
|
217
|
+
|
218
|
+
rates = []
|
219
|
+
xml = REXML::Document.new(response)
|
220
|
+
success = response_success?(xml)
|
221
|
+
message = response_message(xml)
|
222
|
+
if success
|
223
|
+
rate_estimates = {}
|
224
|
+
xml.elements.each('/*/TransitResponse/ServiceSummary') do |service_summary|
|
225
|
+
service_code = service_summary.get_text('Service/Code').to_s
|
226
|
+
service_code_2 = time_code_mapping[service_code]
|
227
|
+
service_desc = service_summary.get_text('Service/Description').to_s
|
228
|
+
guaranteed_code = service_summary.get_text('Guaranteed/Code').to_s
|
229
|
+
business_transit_days = service_summary.get_text('EstimatedArrival/BusinessTransitDays').to_s
|
230
|
+
date = service_summary.get_text('EstimatedArrival/Date').to_s
|
231
|
+
rate_estimates[service_name_for(origin, service_code_2)] = {:service_code => service_code, :service_code_2 => service_code_2, :service_desc => service_desc,
|
232
|
+
:guaranteed_code => guaranteed_code, :business_transit_days => business_transit_days,
|
233
|
+
:date => date}
|
234
|
+
end
|
235
|
+
end
|
236
|
+
return rate_estimates
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
def parse_rate_response(origin, destination, packages, response, options={})
|
242
|
+
rates = []
|
243
|
+
xml = REXML::Document.new(response)
|
244
|
+
success = response_success?(xml)
|
245
|
+
message = response_message(xml)
|
246
|
+
transits = options[:transit]
|
247
|
+
if success
|
248
|
+
rate_estimates = []
|
249
|
+
|
250
|
+
xml.elements.each('/*/RatedShipment') do |rated_shipment|
|
251
|
+
service_code = rated_shipment.get_text('Service/Code').to_s
|
252
|
+
service = rated_shipment.get_text('Service/Code').to_s
|
253
|
+
negotiated_rate = rated_shipment.get_text('NegotiatedRates/NetSummaryCharges/GrandTotal/MonetaryValue').to_s
|
254
|
+
total_price = negotiated_rate.blank? ? rated_shipment.get_text('TotalCharges/MonetaryValue').to_s.to_f : negotiated_rate.to_f
|
255
|
+
currency = negotiated_rate.blank? ? rated_shipment.get_text('TotalCharges/CurrencyCode').to_s : rated_shipment.get_text('NegotiatedRates/NetSummaryCharges/GrandTotal/CurrencyCode').to_s
|
256
|
+
|
257
|
+
rate_estimates << ActiveMerchant::Shipping::RateEstimate.new(origin, destination, ActiveMerchant::Shipping::UPS.name,
|
258
|
+
service_name_for(origin, service_code),
|
259
|
+
:total_price => total_price,
|
260
|
+
:currency => currency,
|
261
|
+
:service_code => service_code,
|
262
|
+
:packages => packages
|
263
|
+
)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
ActiveMerchant::Shipping::RateResponse.new(success, message, Hash.from_xml(response).values.first, :rates => rate_estimates, :xml => response, :request => last_request)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|